关于缓存一致性的问题,今天有时间总结一下
缓存一致性即确保缓存中的数据与数据库中的数据保持同步
技术方案
1. 先写缓存再写数据库
不能保证先写了缓存就能先写数据库,所以会导致数据库错误的问题
2. 先写数据库再写缓存
同理,不能保证先写数据库的就能先写缓存,所以导致缓存数据是错误的
1,2这两种都是不建议使用的,因为是直接去更新缓存去了,一般我们都是去删除缓存
3. 先删除缓存再写数据库
写操作删除缓存之后,还没来及写,另一个就去读了,会更新为旧的缓存
这个到缓存一致性的时间窗口比较长,只有到旧的缓存过期或者下一次删除缓存(也就是跟新操作时)才会一致
4. 先写数据库再删除缓存(Cache Aside Pattern)
缓存不一致的时间窗口较短,也就是说这种模型会存在一个很小周期的缓存与数据库不一致的情况,不过对于绝大多数的情况来说,是可以容忍的。除去一些电商库存、列车余票等对数据比较敏感的情况,比较适合绝大多数业务场景
理想情况下,删缓存在写缓存之后,不会出现数据不一致的情况
极端情况下,删缓存在写缓存之前,也会出现数据不一致时间窗口不确定的情况,所以有了延时双删技术
5. 先删除缓存再写数据库,再删除缓存(缓存双删技术)
为了保证删缓存在写缓存之后,可以使用延迟队列或者引入三方消息队列去做。
如果消息队列更新缓存失败了呢?其实这一点还好,凭借消息队列客户端消费的重试规则,如果更新失败次数都达到客户端重试阈值还是不行,那一定是数据或者缓存中间件有问题。
当然,如果重试次数多了,也必然会面临缓存与数据库不一致的时间变长了,这个是需要清楚的。
通过该技术方案,可以很好达到缓存与数据库最终一致性。
6. 先写数据库,通过 BinLog 异步更新缓存
这种方案是我认为最终一致性最为值得尝试以及使用的。但是有一句话说的是没有绝对合适的技术,只有相对适合的技术,这种方案实现是也存在一些技术问题,稍后会给大家详细说明。