上一篇文章中,我们详细介绍了 guava cache 的使用方法,尤其是在其中重点介绍了 guava cache 异步回种的用法,那么,性能优异的异步回种缓存究竟是如何实现的呢?本文我们就来详细阅读 guava cache 的完整流程代码,抽丝剥茧,学习其中的思想与智慧。
guava cache 异步回种基本思想:
cache.get() 完整流程图:
如图所示,下述场景下,缓存直接通过加锁同步调用的方式获取数据:
guava cache 在上述情况下调用 lockedGetOrLoad() 方法获取数据,这个方法中,通过加 AQS 锁避免多个线程同时 load 获取数据,然后通过回调 load() 方法同步获取数据。
如果第一步操作中,缓存中数据获取正常,没有超过 expireTime,那么就需要判断是否过了 refreshTime 了。
expireTime 与 refreshTime 的区别如下:
如图所示,scheduleRefresh() 方法的流程并不复杂:
上述流程中,refresh() 方法具体执行的流程就是 loadAsync() 方法,如图所示:
loadAsync 方法分两种情况:
无论是通过同步 load 方法还是异步 reload 方法获取数据,都会最终封装成 Future 对象,并且为这个 Future 对象添加 Listener,从而能够在数据获取完成后,设置缓存及更新缓存中数据的状态。
了解了 guava cache 异步回种的基本思想,也许你会觉得这一套解决方案的实现是如此简单,那么,我们知道,memcache、redis 都是只有提供了同步接口的,那么,你是否可以在此基础上实现一套异步回种方案呢?