【问题标题】:Spring Cache Abstraction with Hazelcast Doesn't Evict Key From Cache使用 Hazelcast 的 Spring Cache 抽象不会从缓存中驱逐密钥
【发布时间】:2020-07-14 20:07:07
【问题描述】:

使用以下配置,我的返回对象被缓存,但是当我尝试手动逐出一个键时它不起作用。

@Configuration
@EnableCaching
public class HazelCastConfiguration {

    @Bean
    public HazelcastCacheManager hazelcastCacheManager() {
        return new HazelcastCacheManager(Hazelcast.newHazelcastInstance(hazelcastConfig()));
    }

    @Bean
    public Config hazelcastConfig() {
        return new Config()
                .setInstanceName("hazelcast-instance")
                .addMapConfig(new MapConfig()
                        .setName("myCache")
                        .setMaxSizeConfig(new MaxSizeConfig())
                        .setEvictionPolicy(EvictionPolicy.LRU)
                        .setStatisticsEnabled(true)
                        .setTimeToLiveSeconds(-1));
    }
}

缓存方法:

@Override
@Cacheable(value = "myCache", unless = "#result == null", key = "{#someString, #someLong, #someInteger}")
public List<MyReturnObject> methodWithCachedResults (String someString, Long someLong, Integer someInteger) { 
    //my logic 
}

一个示例辅助方法:

public void evictKey(String aString, Long aLong, Integer anInteger) {
         IMap<Object, Object> hazelcastCache = Hazelcast.getHazelcastInstanceByName("hazelcast-instance").getMap("myCache");
         hazelcastCache.evict(Arrays.asList(aString, aLong, anInteger));
         logger.info("{}", hazelcastCache.keySet());
    }

当我触发上述方法时,即使我强制驱逐密钥,它也会记录密钥。

当我尝试使用 CacheManager 时,结果是一样的:

@Autowired
private HazelcastCacheManager cacheManager;

public void evictKey(String aString, Long aLong, Integer anInteger) {

    cacheManager.getCache("myCache").evict(Arrays.asList(aString, aLong, anInteger));

}

但是,如果我尝试这样做,它会清除它明显声明的整个缓存:

public void evictKey(String aString, Long aLong, Integer anInteger) {
      IMap<Object, Object> hazelcastCache = Hazelcast.getHazelcastInstanceByName("hazelcast-instance").getMap("myCache");
      hazelcastCache.clear();
}

顺便说一句,检查 keySet().contains(Arrays.asList...) 返回 true。

【问题讨论】:

  • 是什么让您认为将所有元素存储在列表中是正确的关键?因为它不是并且因为它不是,所以密钥不匹配并且不会被驱逐。您应该使用带有 @CacheEvict 注释的方法从缓存中删除元素,因为这将重新创建正确的键。
  • 实际上,我之前使用过 EhCache 实现,并且使用该列表作为键就像一个魅力。我实现了将元素存储在缓存中并以我现在尝试的相同方式驱逐缓存。我尝试使用 @CacheEvict 而不是使用列表,它仍然说 keySet() 包含 SimpleKey 对象而不是驱逐键。
  • logger.info("{}", hazelcastCache.keySet()); 返回的键的类型是什么?您正在逐出列表键,但如果实际键不是列表,它将找不到它。
  • 正如我之前所说,keySet().contains(Arrays.asList(aString, aLong, anInteger)) 返回 true。我的意思是,这些列表是否有可能是相等但不能被驱逐的?
  • 查看实际的 hazelcast 集成部分,他们使用delete 而不是evict。但是如前所述,我强烈建议使用注释或 Spring 缓存抽象来执行驱逐,而不是直接尝试访问缓存。

标签: spring-boot caching hazelcast spring-cache


【解决方案1】:

这远非显而易见,但这里有两个 List 的实现。

@Cacheable 将创建一个java.util.ArrayList 的实例。

Arrays.asList 将创建一个java.util.Arrays.ArrayList 的实例。

这应该更清楚:

    public void evictKey(String aString, Long aLong, Integer anInteger) {
        IMap<Object, Object> hazelcastCache = Hazelcast.getHazelcastInstanceByName("hazelcast-instance").getMap("myCache");
        java.util.List<Object> keyToEvict = Arrays.asList(aString, aLong, anInteger);
        boolean success = hazelcastCache.evict(Arrays.asList(aString, aLong, anInteger));
        logger.info("Evicted {}, {} ==  {}", keyToEvict, keyToEvict.getClass(), success);
        for (Object key : hazelcastCache.keySet()) {
            logger.info("Remaining key {}, {}", key, key.getClass());
        }
   }

【讨论】:

    猜你喜欢
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-23
    • 1970-01-01
    • 2019-07-05
    • 1970-01-01
    相关资源
    最近更新 更多