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

Hazelcast中通过@CachePut添加的缓存条目为何在Map中不可见?

Hazelcast缓存@CachePut写入后无法通过API读取的问题分析与解决

核心问题

使用Spring的@CachePut向Hazelcast的testmap缓存写入条目后,直接通过Hazelcast实例的getMap()/getReplicatedMap()获取的集合size始终为0,但缓存配置的总备份计数显示为1。

代码中的关键问题

  1. Hazelcast实例获取错误
    在TestController的doCB方法中,手动new HazelcastConfig()并调用hazelcastConf()会生成全新的Config对象,这和Spring容器中由@Bean管理的HazelcastInstance实例不属于同一上下文。通过Hazelcast.getHazelcastInstanceByName()获取的实例,并非Spring Cache实际使用的那个。

  2. 缓存类型不匹配
    Spring Cache与Hazelcast集成时,默认使用的是Hazelcast的IMap(即getMap()返回的类型),而你同时尝试了ReplicatedMap和MultiMap——这两种是完全不同的缓存结构,自然无法读取到IMap中的数据。

  3. 缓存键的序列化差异
    @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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:20:55