前言
1. 服务涉及XSLT模板转换,在每台服务器上维护了一个本地纯内存缓存,避免频繁创建Transform对象
2. 定时20分钟从数据库更新模板数据到内存缓存,每次全量更新缓存耗时7秒左右
3. 担心紧急情况更新模板后本地缓存没同步,无法及时变更
方案
本地缓存初始化时,新增一个本地Map用来记录当前本地缓存中模板数据的初始化时间
Map:
map(template1) => initTimestamp
map(template2) => initTimestamp
map(templateN) => initTimestamp
本地缓存自动更新时,重新刷新该Map中的所有时间戳
变更模板时将模板映射成key,更新时间戳作为value,写入redis。对应key的ttl为缓存的刷新时间20分钟
Redis:
map(template1) => updateTimestamp1
map(template2) => updateTimestamp2
各个实例中需要获取本地缓存中的模板数据前,先查Redis中是否有map(template)对应的值。若有值则对比对应值与本地Map中的时间戳,若Timestamp(Redis) > Timestamp(LocalMap),则重新从数据库查询最新的模板并更新到本地缓存,并更新Timestamp(LocalMap)。反之直接从缓存中获取数据即可
后记
上述方案可以保证缓存的最终一致性,在并发请求多的时候对Redis有一次额外的调用
由于本地Transform无法缓存到Redis供所有实例使用,所以仅使用了本地缓存。但若其他场景可以将缓存对象全量写入Redis,则可以使用JetCache提供的本地缓存+Redis缓存的组合。通过将本地缓存的时间设置一个较小值,当本地缓存失效后会自动从远程Redis缓存获取数据。那么我们只需要在更新模板的时候手动删除Redis缓存即可,JetCache的初始化方法会帮我们重新创建缓存并读取到本地。这样缓存不一致的时间最多则是JetCache本地缓存的失效时间