能否用Ignite Cache实现带RDBMS持久化的分地域日访客计数器?
用IgniteCache实现网站地域访客计数器方案
需求梳理
- 按地域统计每日网站访客数
- 前一日计数器自动过期,当日首次调用时初始化新计数器为0并开始计数
- 以地域(结合日期)为键、计数器数值为值存储数据
- 通过原子递增操作实现自动计数
- 数据需持久化到RDBMS
用户期望的参考代码(Memcached风格)
ClientConfiguration cfg = new ClientConfiguration().setAddresses("localhost:10800"); IgniteClient igniteClient = Ignition.startClient(cfg); ClientCache<String, Integer> clientCache = igniteClient.getOrCreateCache("mycache"); clientCache.increment("mykey", 0); // 键不存在时用默认值0初始化,然后递增;Ignite Client原生无此方法,但可通过其他方式实现
可行实现方案
可以通过IgniteCache的getAndCompute方法结合自定义EntryProcessor实现原子递增逻辑,同时配置缓存过期策略与RDBMS持久化,完全覆盖所有需求。
1. 缓存核心配置
先配置带24小时过期、RDBMS持久化的缓存:
// 初始化Ignite客户端配置 ClientConfiguration cfg = new ClientConfiguration() .setAddresses("localhost:10800") .setCacheConfiguration( new ClientCacheConfiguration("visitor-counter-cache") // 设置24小时过期,自动清理前一日数据 .setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(Duration.ofHours(24))) // 开启持久化并配置RDBMS存储(以MySQL为例) .setPersistenceEnabled(true) .setStorageConfiguration(new StorageConfiguration() .setDefaultDataRegionConfiguration(new DataRegionConfiguration() .setPersistenceEnabled(true)) .setDatabaseConfiguration(new DatabaseConfiguration() .setJdbcConnectionConfiguration(new JdbcConnectionConfiguration() .setDriver("com.mysql.cj.jdbc.Driver") .setUrl("jdbc:mysql://localhost:3306/ignite_visitor_db") .setUsername("root") .setPassword("your_db_password"))))); IgniteClient igniteClient = Ignition.startClient(cfg); ClientCache<String, Integer> visitorCache = igniteClient.getOrCreateCache("visitor-counter-cache");
2. 原子递增计数实现
使用EntryProcessor实现原子化的"不存在则初始化+递增"逻辑,键采用{日期}_{地域}格式确保每日独立统计:
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import org.apache.ignite.client.IgniteClient; import org.apache.ignite.client.ClientCache; import org.apache.ignite.binary.BinaryEntry; // 获取当日访客数并原子递增 public int incrementAndGetVisitorCount(String region) { // 生成当日日期键前缀,格式如"20240520" String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String cacheKey = String.format("%s_%s", dateStr, region); // 原子执行:不存在则初始化为0后递增为1,存在则直接+1 return visitorCache.getAndCompute(cacheKey, (BinaryEntry<String, Integer> entry) -> { Integer currentCount = entry.getValue(); int newCount = (currentCount == null) ? 1 : currentCount + 1; entry.setValue(newCount); return newCount; }); }
方案说明
- 自动过期:通过
CreatedExpiryPolicy设置24小时过期,前一日的计数器会自动被清理,当日首次调用时会生成新键并初始化计数。 - 原子计数:
EntryProcessor在Ignite集群端执行,保证操作的原子性,避免并发问题。 - RDBMS持久化:配置JDBC存储后,缓存数据会同步持久化到指定的关系型数据库,满足持久化需求。
- 地域+日期键设计:确保每个地域的每日计数器独立,不会跨日期干扰。
内容的提问来源于stack exchange,提问作者Neeraj Mukati
相关产品推荐
相关产品推荐

