Hazelcast中通过@CachePut添加的缓存条目为何在Map中不可见?
核心问题
使用Spring的@CachePut向Hazelcast的testmap缓存写入条目后,直接通过Hazelcast实例的getMap()/getReplicatedMap()获取的集合size始终为0,但缓存配置的总备份计数显示为1。
代码中的关键问题
Hazelcast实例获取错误
在TestController的doCB方法中,手动new HazelcastConfig()并调用hazelcastConf()会生成全新的Config对象,这和Spring容器中由@Bean管理的HazelcastInstance实例不属于同一上下文。通过Hazelcast.getHazelcastInstanceByName()获取的实例,并非Spring Cache实际使用的那个。缓存类型不匹配
Spring Cache与Hazelcast集成时,默认使用的是Hazelcast的IMap(即getMap()返回的类型),而你同时尝试了ReplicatedMap和MultiMap——这两种是完全不同的缓存结构,自然无法读取到IMap中的数据。缓存键的序列化差异
@CachePut指定的key为"1",这个字符串键在Spring Cache中会经过序列化处理;如果直接用Hazelcast原生API获取时,序列化方式不一致,会导致无法匹配到对应的缓存条目。
修复步骤
步骤1:注入Spring管理的HazelcastInstance
修改TestController,直接注入Spring容器托管的HazelcastInstance,避免手动创建新的Config实例:
@RestController @RequestMapping("/v1") public class TestController { @Autowired private TestService testService; @Autowired private HazelcastInstance hazelcastInstance; // 直接注入Spring管理的实例 @GetMapping("/testCB") public ResponseEntity<?> doCB() { Map<String, String> resp = new HashMap<>(); String id = testService.getId(); if (null != id) { resp.put("id", id); } // 获取Spring Cache实际使用的IMap IMap<Object, Object> testMap = hazelcastInstance.getMap("testmap"); System.out.println("缓存条目数量:" + testMap.size()); // 按@CachePut指定的key取值,保持类型一致 System.out.println("key=1的缓存值:" + testMap.get("1")); return ResponseEntity.status(HttpStatus.ACCEPTED).body(resp); } }
步骤2:统一序列化配置
确保Spring Cache与Hazelcast原生API使用相同的序列化器,避免键值匹配失败。可以在HazelcastConfig中配置全局或指定map的序列化规则:
@Configuration public class HazelcastConfig { @Bean public Config hazelcastConf() { Config c = new Config() .setInstanceName("hazelcast-instance") .addMapConfig( new MapConfig() .setName("testmap") .setEvictionConfig( new EvictionConfig() .setEvictionPolicy(EvictionPolicy.LRU) .setMaxSizePolicy(MaxSizePolicy.PER_NODE) .setSize(1000) ) .setTimeToLiveSeconds(500000) // 为该map配置序列化器,与Spring Cache保持一致 .setEntrySerializer(new JavaSerializationSerializer()) ); c.getNetworkConfig().getRestApiConfig().setEnabled(true); c.getNetworkConfig().getRestApiConfig().enableGroups(RestEndpointGroup.DATA); // 全局序列化配置,保证String类型键的序列化一致 c.getSerializationConfig().addSerializerConfig( new SerializerConfig() .setTypeClass(String.class) .setImplementation(new StringSerializer()) ); return c; } }
步骤3:验证缓存写入逻辑
@CachePut是在方法执行完成后才写入缓存,需确保getId()方法正常返回非null值。可以在方法返回后通过Hazelcast管理控制台查看缓存条目,或添加日志确认写入状态。
额外注意事项
- 不要混用Hazelcast不同类型的缓存结构(IMap、ReplicatedMap、MultiMap),Spring Cache默认使用IMap,只需操作
getMap()返回的实例。 - 确保Spring Boot与Hazelcast版本兼容,避免版本不匹配引发的序列化或集成问题。
- 开启Hazelcast日志,可查看缓存写入、读取的详细流程,帮助快速定位问题。
内容的提问来源于stack exchange,提问作者alpheus

