在业务中,我们使用缓存来换缓解数据库压力,只有当缓存不存在或者缓存失效才让请求访问到数据库,这就不可避地需要保证缓存和数据库的数据的一致性

常见的,有3种更新策略:

  1. 先更新数据库,再更新缓存
  2. 先删除缓存,再更新数据库
  3. 先更新数据库,再删除缓存

先更新数据库,再更新缓存

这种方案不推荐,因为考虑有两个写请求A、B,当A更新数据库后,B请求又更新了数据库,但是因为A更新缓存的时候有网络波动导致,B的更新缓存早于A,则会导致缓存中的数据是脏数据的情况

先删除缓存,再更新数据库

这种方案也不推荐,考虑一个写请求A,一个读请求B,当A删除缓存后,B请求到达,查询不到缓存,则立即查询数据库,并更新缓存,A请求此时更新数据库,则导致缓存和数据库数据不一致

先更新数据库,再删除缓存

推荐,先更新数据库再删除缓存,则可以避免并发的写请求进行缓存更新导致缓存不是最新的数据的情况,当然极端情况下,一个读请求,在更新数据前查询到了数据,在删除缓存后写入了缓存,也会出现数据不一致,但是一般来说读请求效率比写请求更高,不会出现这种情况,

实在需要考虑来确保一致性,也可以采用 延时双删 的方案:在删除缓存后,先sleep,再执行一次删除,具体sleep的时长可以根据业务中一个请求的耗时来决定,确保删除可能的由读请求产生的脏数据。

当然,同步的删除操作,会降低吞吐量,可以考虑将删除操作放在MQ异步执行,或者订阅binlog来异步删除缓存

但是如果缓存删除失败,则也会出现数据不一致的情况,这时候可以考虑重试删除

还可以结合主从同步来考虑,比如延时双删的sleep时间大于主从同步时间,避免从库查到旧数据写入缓存后形成脏数据

最后,可以设置过期时间来确保可能的脏数据被刷新,来达到最终一致性

标签: none

添加新评论