expireAfterAccess:缓存项在单位时间内未发生过读/写操作 即被回收;
expireAfterWrite:缓存项在单位时间内未被更新即被回收;
refreshAfterWrite:缓存项离上一次更新操作多久之后会被 更新。
本文重点说expireAfterWrite与refreshAfterWrite;
expireAfterWrite,当 缓存项过期触发回源操作时,GuavaCache会通过重入锁ReentrantLock 严格地控制单机只能有一个线程在执行操作,而其他线程则必须阻塞 等待直至回源操作完成,不过当回源操作结束后,之前那些被阻塞的 线程仍然会逐一获取锁来验证回源结果;也就是说,每个线程必须轮 流地经历取锁、取值,以及释放锁的过程,这样会存在一定程度上的 性能损耗。而 refreshAfterWrite 机制则可以有效避免 expireAfter Write 机制在并发环境下因为锁资源竞争所带来的性能损耗,同expir eAfterWrite类似,在执行回源操作时,单机仍然只允许一个线程在执 行操作,但其他线程并不会阻塞,而是直接返回旧值;这么做虽然可 以提升性能,但却仍然存在一个明显的问题,那就是refreshAfterWri te机制并不能够严格地确保返回值都是新值。
另,GuavaCache的过期监听器也是一个利器,用来做数据 【粗估式】的汇总或者同步也非常合适,此时可大幅度提升性能及吞吐量,但其中有个坑点:guava cache的过期逐出与它的get是同步的,如有get操作,并且removalListener有网络IO等耗时较长的操作时,会因阻塞导致读写接口的性能下降; 笔者在实际生产环境中,结合使用了RemovalListeners.asynchronous来解耦数据的过期监听器与cache的访问,接口性能有很大提升;
当然local cache的一项副作用,此处removalListener无法保证事务,数据不是百分百准确,只能通过retry、幂等来尽量保证数据准确性,所以比较适合粗略的场景;