You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Infinispan的Java应用在线用户数统计并发问题求助

解决Infinispan在线用户数统计的并发同步问题

问题根源

你遇到的是典型的读-改-写竞态条件:多个并发请求同时读取缓存中的用户数,各自加1后写回,导致最终计数比实际登录用户数少(比如两个请求同时读10,都写11,实际应该是12)。

解决方案

Infinispan提供了原生原子操作API来规避这类问题,以下是几种可靠实现方式:

1. 使用compute()原子方法

Infinispan的AdvancedCache提供的compute()方法,会在缓存条目上执行原子计算逻辑,确保读-改-写全程线程安全:

// 获取AdvancedCache实例
AdvancedCache<String, Integer> advancedCache = cache.getAdvancedCache();

// 原子更新在线用户数
Integer newCount = advancedCache.compute("online-users", (key, currentValue) -> {
    // 初始状态(无缓存值)从0开始计数
    return (currentValue == null) ? 1 : currentValue + 1;
});

该方法会自动处理锁机制,同一时间仅允许一个线程修改目标缓存条目,彻底消除竞态条件。

2. 使用merge()方法(适合初始值明确场景)

如果默认初始值固定为0,可使用merge()方法合并现有值与增量,内部同样是原子操作:

// 每次登录时,现有值加1,无值则从0+1开始
Integer newCount = cache.merge("online-users", 1, (existing, valueToAdd) -> existing + valueToAdd);

3. 分布式锁(自定义复杂场景)

若需更灵活的业务逻辑控制,可手动获取分布式锁保护读-改-写流程:

// 获取分布式锁管理器
LockManager lockManager = advancedCache.getLockManager();

// 锁定目标缓存键
lockManager.lock("online-users");
try {
    Integer currentCount = cache.get("online-users");
    Integer newCount = (currentCount == null) ? 1 : currentCount + 1;
    cache.put("online-users", newCount);
} finally {
    // 必须在finally块释放锁,避免死锁
    lockManager.unlock("online-users");
}

额外注意事项

  • 登出操作需复用相同原子方法(比如compute()中减1),避免登出环节出现并发问题。
  • 集群环境下,Infinispan原子操作会自动同步所有节点,无需额外处理一致性。
  • 绝对避免单独使用get()+put()组合,这种非原子操作在并发场景下必然导致数据不一致。

内容的提问来源于stack exchange,提问作者Gagan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:45:27