当前位置: 首页 > 知识库问答 >
问题:

具有复杂条件驱逐的缓存

堵景天
2023-03-14

我试图使用咖啡因spring boot starter缓存实现以下缓存逻辑:

  1. 如果过期时间已经过去,条件(需要计算和I/O)被评估为TRUE,然后强制获取数据并更新缓存。
  2. 如果过期时间已经过去,条件(需要计算和I/O)被计算为FALSE,那么不要使缓存数据无效,并从缓存中检索值。
  3. 如果过期时间未过,则从缓存中检索该值。

我按照这个指南工作:https://www.baeldung.com/spring-boot-caffeine-cache

我尝试了所有类型的方法使用@CachePUT@CacheEvket@Cacheable对对象的getter方法我;m缓存,但核心问题是我需要条件驱逐一个过期时间和另一个逻辑,但是这些注释不能控制是否驱逐...也许这可以使用Scheduler来完成?

共有2个答案

钮誉
2023-03-14

看来你不是用咖啡因作为缓存系统。

在这种情况下,使用自定义类并在简单映射中保存数据会更好,因为它为您提供了更大的灵活性。

这是一副骷髅

public class SpecialCache {
    private Map<String, SpecialCache.Entry> map = new HashMap<>();

    private boolean specialCondition(String key) {
        ...
    }

    private Object fetch(String key) {
       ...
    }


    public Object get(String key) {
        SpecialCache.Entry entry = map.get(key);
        if (entry.getExpiringEpoch() > System.currentTimeMillis()) {
            if (specialCondition(key)) {
                Object data = fetch(key);
                entry.setExpiringEpoch(...);
                entry.setData(data);
                return data;
            } else {
                return entry.getData();
            } 
        } else {
            return entry.getData();
        }
    }

    @Data
    public static class Entry {
        private long expiringEpoch;
        private Object data;
    }
}

在这个例子中,我在缓存中添加了特殊条件和读取方法。您还可以将方法作为lambda函数传递给get方法,以获得更大的灵活性。

代码必须以完成,例如,您需要添加:

  • 检查缓存中不存在的键
  • 填充缓存的方法(一个放?)
宗政卓
2023-03-14

我想你正在寻找刷新后写并覆盖CacheLoader.reload(K, V)。下面是解释细节的帖子:https://github.com/ben-manes/caffeine/wiki/Refresh

对您的案例的实现类似于:

java prettyprint-override">@Log4j2
@Configuration
public class CacheConfig {

    @Bean
    public Cache<String,Item> caffeineConfig() {
        return Caffeine.newBuilder()
            .refreshAfterWrite(10, TimeUnit.SECONDS)
            .build(new ConditionalCacheLoader<>(this::shouldReload, this::load));
    }

    private Item load(String key){
        //load the item
        return null;
    }

    private boolean shouldReload(Item oldValue){
        //your condition logic here
        return true;
    }


    private static class Item{
         // the item value can contain any data
    }

    private static class ConditionalCacheLoader<K,V> implements CacheLoader<K,V>{
        private final Predicate<V> shouldReload;

        private final Function<K,V> load;

        protected ConditionalCacheLoader(Predicate<V> shouldReload, Function<K, V> load) {
            this.shouldReload = shouldReload;
            this.load = load;
        }

        @Override
        public V load(K key) throws Exception{
            return load.apply(key);
        }

        @Override
        public V reload(K key, V oldValue) throws Exception {
            if (shouldReload.test(oldValue)){
                return load(key);
            }else {
                return oldValue;
            }
        }
    }
}
 类似资料:
  • 我使用Spring缓存抽象,定义了多个缓存。有时,当数据更改时,我想逐出多个缓存。是否可以使用Spring的CacheExit注释逐出多个缓存?

  • 什么是 Nutz.Dao 中的复杂SQL条件 对于 Nutz.Dao 来说,它本质上就是将你的 Java 对象转化成 SQL,然后交给 JDBC 去执行。 而 SQL 中,当执行数据删除和查询操作时,最常用的就是 WHERE 关键字。 WHERE 关键字后面的就是所谓的复杂查询条件 Nutz.Dao 将如何如何使用这个条件 Dao 接口的 clear 方法和 query 方法的第二个参数,就是为了

  • 嗨,我在执行方法时遇到清理缓存的问题。这是我的配置和缓存方法: 我要缓存的这个方法: 在执行此方法时,我希望按类型清理缓存: 新闻消息对象看起来像: 缓存工作正常,第一次查询DB时,第二次从缓存中提取数据。问题是当我更新数据时,@CacheEvict不会清理缓存。我试图使用以下注释清理所有缓存:@cacheexit(cacheNames={CacheConfiguration.RSS\u NEWS

  • 我需要一些使用jxls阅读器的帮助(http://jxls.sourceforge.net/reference/reader.html). 我对循环一行表示特定java对象的工作表很满意,但在嵌套循环的情况下,我被难倒了。 我需要将上述excel表映射到以下pojo: 我的问题是定义lookbreakcondition来读取内部对象。请注意,类对象的loopbreakcondition需要以下内容

  • 问题内容: 我有许多JTable的自定义编辑器,可以说是缺乏可用性,尤其是在使用键盘进行编辑方面的可用性。 这样做的主要原因是,我的编辑器总是以类似(尽管通常更复杂)的情况创建: IE面板内部有多个组件。实际的文本编辑器是作为编辑器返回的组件的后代。因此,除了呈现问题之外,据我所知,JTable集中了方法返回的组件,因此当您按下突出显示单元格的按键时,它将焦点和按键传递给面板,认为是编辑器。 无论

  • 复杂的表达式 当你有一个复杂的 if 子句的时候,你应该把它们提取出来赋给一个 BOOL 变量,这样可以让逻辑更清楚,而且让每个子句的意义体现出来。 BOOL nameContainsSwift = [sessionName containsString:@"Swift"]; BOOL isCurrentYear = [sessionDateCompontents year] == 2