首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Guava缓存的概率提前到期

问使用Guava缓存的概率提前到期
EN

Stack Overflow用户
提问于 2016-10-08 07:29:31
回答 1查看 325关注 0票数 2

我有一个用expireAfterWrite(20, TimeUnit.MINUTES)创建的Guava缓存。缓存在创建时也会使用数十个条目进行初始化。当值过期时,客户端应该调用外部服务并刷新缓存。

问题是-所有初始化的值将同时过期,并且在20分钟后,客户端将几乎在同一实例中调用该服务数十次。

我不希望这事发生。为了避免这种情况-一个想法是在TTL之前使用probabilistically expire the entries,这样服务就不会在同一时间受到太多的冲击。

不幸的是,我没有看到使用Guava缓存的选项--至少Wiki或Javadoc没有弹出任何东西。有没有其他可用的库?为此,我尽量避免编写自己的缓存实现。

EN

回答 1

Stack Overflow用户

发布于 2017-12-06 16:41:31

缓存预热是一个相当复杂的话题,因此有很多合理的方法,但不一定是单一的“正确”方法。一个简单的选择是只需在未来的交错时间触发额外的写入,以便重置到期时间:

代码语言:javascript
复制
public static <K, V> void staggerCacheExpiration(
    Cache<K, V> cache, long maxExpiration, TimeUnit unit, ScheduledExecutorService scheduler) {
  for (Entry<K, V> e : cache.asMap().entrySet()) {
    long delay = ThreadLocalRandom.current().nextLong(0, maxExpiration);
    scheduler.schedule(() -> cache.put(e.getKey(), e.getValue()), delay, unit);
  }
}

依赖于Cache本身的任何方法的一个关键问题是,只有在调用者需要该值时,您才会触发(可能代价高昂的)刷新。最好不要使用expireAfterWrite()或refreshAfterWrite(),而是运行一个负责按顺序更新每个键的专用线程。通过让单个线程更新所有键,您将自然地避免同时刷新多个键的任何热点,也避免阻塞任何依赖于缓存中的值的线程。

正如Ben Manes建议的那样,您可能更喜欢将Cache封装在自己的类型中,这样您选择的任何行为都不会暴露给调用者。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39927094

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档