【问题标题】:Guava LoadingCache: Why use refreshAfterWrite and expireAfterWrite togetherGuava LoadingCache:为什么一起使用 refreshAfterWrite 和 expireAfterWrite
【发布时间】:2017-09-11 15:14:54
【问题描述】:

我阅读了这篇解释 Guava Cache 的文档:CachesExplained。我确实了解 refreshAfterWrite 和 expireAfterWrite 在做什么。不过,文档在解释 refreshAfterWrite 的同时,也提到了这一点:

"因此,例如,您可以在同一个缓存中同时指定 refreshAfterWrite 和 expireAfterWrite,这样每当条目符合刷新条件时,条目的过期计时器就不会被盲目重置,所以如果一个条目符合刷新条件后不查询,允许过期。"

这是让我感到困惑的部分。根据我的理解,如果你想让某个键自动刷新,你只需要指定 refreshAfterWrite 即可。为什么我们在使用 refreshAfterWrite 时还要使用 expireAfterWrite?

【问题讨论】:

    标签: java guava google-guava-cache


    【解决方案1】:

    在某些情况下,您希望缓存条目具有相关性,因此您可以设置刷新持续时间(执行起来可能更轻松(和异步),而不是在逐出后完全获取,因此不同),但是同时,如果你的缓存是有界的,你会想要驱逐条目,这就是expireAfterWrite 的用途。通过同时设置它们,您将确保某个条目在一定时间后被逐出,即使它已被刷新。

    另请注意,两者的操作方式不同:

    刷新与驱逐并不完全相同。正如 LoadingCache.refresh(K) 中所指定的,刷新一个键会为该键加载一个新值,可能是异步的。刷新键时仍会返回旧值(如果有),与驱逐相反,驱逐会强制检索等到重新加载值。

    【讨论】:

    • 有道理。但是我也有这个问题:如果我只使用expireAfterWrite(),应该也够了吧? expireAfterWrite() 驱逐旧条目。每当我调用 get() 时,缓存加载的新值或缓存中的值(取决于值是否过期)都会返回给我。解释 refreshAfterWrite() 的文档说只有在查询条目时才会真正启动刷新。那么使用 refreshAfterWrite() 有什么意义呢?可以举个例子吗?
    • 刷新操作可能更轻(和异步),然后是驱逐后的完整提取操作。我已将此注释添加到答案正文中。
    • 刷新将重置过期的写入时间戳。目的是某些条目可能非常热,并且在到期时,调用者阻塞负载时会出现用户可见的延迟。刷新允许重新加载活动条目而不会产生此成本。如果不活动,则到期将开始并驱逐。
    • 如果我想要 1) 大约每分钟刷新一次 2) 总是异步 3) 自动清理(如果项目被删除,它应该从缓存也在〜1分钟内)。我是否正确,如果我的 CacheLoader 是同步的,那么番石榴缓存也是同步的?
    • 是的@OlegVazhnev,如果您不实现异步刷新方法,您的获取将等待每个刷新间隔。如果你设置你的 refreshAfterWrite(50s) 和 expireAfterWrite(5m) 那么第一个 get isd 加载同步,然后 50s 所有的 get 都从缓存中提供。 50 秒后,它仍然从缓存中提供,但加载器已启动。然后加载器可能会返回一个值(或丢失)。只要您在 5m 之前收到请求,该条目就永远不会因为年龄而过期(因为刷新会写入它)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多