Redisson RLocalCachedMap开启UPDATE同步策略多实例缓存计数不一致
RLocalCachedMap实例间计数不一致原因分析
- 核心原因是
LocalCachedMapOptions.SyncStrategy.UPDATE策略的特性限制:该策略仅同步已存在于本地缓存中的条目的更新、删除事件,不会同步新增条目的事件。应用启动时所有实例预加载了全量缓存,所以初始计数一致,运行过程中新写入Redis的键,只有执行写入操作、或者后续主动读取过该键的实例才会将其存入本地缓存,其余未接触过该键的实例不会收到同步通知,本地缓存自然不会包含新增键,导致计数少于Redis侧HLEN查询的真实值。 - 本地缓存淘汰策略触发:如果配置了
timeToLive、maxIdleTime超时时间,或者cacheSize本地缓存容量上限,各实例会根据自身的缓存访问频率淘汰超时、超出容量的条目,淘汰操作不会跨实例同步,不同实例的访问模式不同,淘汰的条目数量也会有差异,进一步拉大计数偏差。 - 缓存同步消息丢失:Redisson的本地缓存同步依赖Redis的Pub/Sub机制,Pub/Sub消息默认无持久化、无投递确认机制,如果实例出现短时间网络抖动、进程GC停顿,就可能出现同步消息丢包,对应实例不会执行对应的缓存更新/删除操作,最终导致计数不一致。
- 旧版本Redisson的API缺陷:3.16.x及之前版本的
RLocalCachedMap.size()方法默认读取本地缓存计数而非Redis侧全局真实计数,如果你调用了该方法获取计数,也会出现返回值和Redis侧不一致的问题。
修复方案
- 如果要求所有实例本地缓存和Redis侧强一致,将同步策略替换为
LocalCachedMapOptions.SyncStrategy.ALL,该策略会同步所有新增、更新、删除事件,所有实例的本地缓存会和Redis侧保持同步。 - 如果仅需要准确的全局计数,不要读取本地缓存的计数,调用
RLocalCachedMap.size()时Redisson会请求Redis侧返回真实的全局Hash长度,RLocalCachedMap.sizeInMemory()方法仅用于获取当前实例本地缓存的条目数量。 - 合理配置本地缓存的超时时间和容量上限,避免不必要的缓存淘汰,对一致性要求较高的场景可以同时开启
invalidateEntryOnChange(true)配置,降低不一致概率。 - 升级到Redisson 3.17及以上稳定版本,规避旧版本的API逻辑缺陷。
内容的提问来源于stack exchange,提问作者eprabab
相关产品推荐
相关产品推荐

