Infinispan失效模式缓存:如何避免新增对象时发送失效消息?
解决Infinispan 13.x 缓存新增触发集群失效的问题
你的核心需求是让失效模式的应用缓存在新增元素时不发送集群失效消息,仅在更新/删除操作时触发,和之前EhCache的replicatePuts=false行为一致,这完全可行,以下是几种实用方案:
1. 配置层面直接实现(最推荐)
Infinispan 13.x 原生支持控制失效模式下put操作的集群通知行为,直接在缓存配置中添加invalidation.puts=false即可,无需修改业务代码,且能正常兼容Spring Cache抽象。
XML配置示例
<cache-container default-cache="default"> <transport stack="jgroups"/> <cache name="your-invalidation-cache" mode="INVALIDATION_SYNC"> <locking isolation="READ_COMMITTED"/> <invalidation puts="false"/> <!-- 关键配置:新增缓存时不发送失效消息 --> </cache> </cache-container>
Spring Boot YAML配置
如果使用application.yml:
infinispan: cache: your-invalidation-cache: mode: INVALIDATION_SYNC invalidation: puts: false
配置生效后,调用cache.put()新增元素时不会向集群发送任何消息,仅删除、替换等修改操作才会触发其他节点的key失效,完美匹配你需要的效果。
2. 自定义拦截器(灵活扩展场景)
如果需要更细粒度的控制(比如仅对特定key或业务场景生效),可以编写自定义CacheInterceptor,将新增的put操作转换为putForExternalRead逻辑。
拦截器代码示例
public class PutToExternalReadInterceptor extends AbstractCacheInterceptor { @Override public Object visitPutCommand(PutCommand command) throws Throwable { // 仅当key不存在时,替换为putForExternalRead逻辑 if (!cache.containsKey(command.getKey())) { return cache.putForExternalRead(command.getKey(), command.getValue()); } // 已存在的key仍执行原put逻辑(触发失效) return super.visitPutCommand(command); } }
注册拦截器
XML方式:
<cache name="your-invalidation-cache" mode="INVALIDATION_SYNC"> <interceptors> <interceptor class="com.yourteam.PutToExternalReadInterceptor" position="AFTER"/> </interceptors> </cache>
Java配置方式(Spring Boot):
@Configuration public class InfinispanConfig { @Bean public CacheManager infinispanCacheManager() { DefaultCacheManager cacheManager = new DefaultCacheManager(); ConfigurationBuilder configBuilder = new ConfigurationBuilder(); configBuilder.clustering().cacheMode(CacheMode.INVALIDATION_SYNC) .interceptors().addInterceptor(new PutToExternalReadInterceptor(), 1); cacheManager.defineConfiguration("your-invalidation-cache", configBuilder.build()); return cacheManager; } }
3. Spring Cache 适配(保留注解使用)
如果使用Spring Cache的@Cacheable、@CachePut等注解,上述配置方案已能让底层缓存不发送失效消息,无需额外修改注解逻辑。若需完全自定义注解对应的缓存操作,可以包装Infinispan的Cache实例,将put方法替换为putForExternalRead:
public class InfinispanExternalReadCache implements org.springframework.cache.Cache { private final org.infinispan.Cache<Object, Object> delegateCache; public InfinispanExternalReadCache(org.infinispan.Cache<Object, Object> delegateCache) { this.delegateCache = delegateCache; } @Override public void put(Object key, Object value) { delegateCache.putForExternalRead(key, value); } // 其他方法直接委托给原生缓存实现 @Override public Object get(Object key) { return delegateCache.get(key); } // 实现剩余的Cache接口方法... }
然后自定义Spring CacheManager返回包装后的缓存实例:
@Configuration public class SpringCacheConfig { @Autowired private org.infinispan.manager.CacheManager infinispanManager; @Bean public org.springframework.cache.CacheManager springCacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); List<org.springframework.cache.Cache> caches = new ArrayList<>(); caches.add(new InfinispanExternalReadCache(infinispanManager.getCache("your-invalidation-cache"))); cacheManager.setCaches(caches); return cacheManager; } }
内容的提问来源于stack exchange,提问作者Janning Vygen
相关产品推荐
相关产品推荐

