guava/caffeine的evict策略探索
背景是上线了一个基于公司内部基于redis缓存组件读的服务时,发现redis数据变化后,超过了本地JVM缓存caffeine)后并没有返回正确的值。
在guava的wiki中有这样一段话:
When Does Cleanup Happen?
Caches built with CacheBuilder do not perform cleanup and evict values “automatically,” or instantly after a value expires, or anything of the sort. Instead, it performs small amounts of maintenance during write operations, or during occasional read operations if writes are rare.
The reason for this is as follows: if we wanted to perform Cache maintenance continuously, we would need to create a thread, and its operations would be competing with user operations for shared locks. Additionally, some environments restrict the creation of threads, which would make CacheBuilder unusable in that environment.
Instead, we put the choice in your hands. If your cache is high-throughput, then you don’t have to worry about performing cache maintenance to clean up expired entries and the like. If your cache does writes only rarely and you don’t want cleanup to block cache reads, you may wish to create your own maintenance thread that calls Cache.cleanUp) at regular intervals.
If you want to schedule regular cache maintenance for a cache which only rarely has writes, just schedule the maintenance using ScheduledExecutorService.
然后就怀疑是guava没有自动evict导致的。但是经过本地测试,发现guava是正常的。并且在guava的CacheBuilder javadoc找到了如下的说明:
If expireAfterWrite or expireAfterAccess is requested entries may be evicted on each cache modification, on occasional cache accesses, or on calls to Cache.cleanUp). Expired entries may be counted by Cache.size), but will never be visible to read or write operations.
证明了是读取不到过期的值的。有时候只读wiki是不够的。
肯定是其他缓存引起的,而当时我们通过redis终端验证了的确没有,这中间是否有其他缓存呢?
最后证明了是公司内部封装的时候还提供了一个本地的jvm缓存,缓存时间是半小时。
guava/caffeine怎么根据时间来进行返回,这个坑留到读源码的时候再来填。