写DB再删缓存如何解决一致性?
作者:程序员马丁
在线博客:https://open8gu.com
大话面试,技术同学面试必备的八股文小册,以精彩回答应对深度问题,助力你在面试中拿个offer。
回答话术
"先写 DB 再删除缓存"是一种常用的缓存一致性解决方案,也被称为“写回策略”或“Write-Through 策略”。
- 当应用程序进行写操作时,首先将数据写入数据库。
- 然后,立即删除相应的缓存数据(或使缓存数据失效)。
- 当下一个读取请求到达时,会发现缓存中没有相应的数据,于是从数据库中读取最新的数据,并将其存储在缓存中。
这种策略的优势在于它保证了数据库和缓存之间的一致性。如果应用程序写入数据库并删除缓存,下一个读取操作将从数据库中获取最新数据,从而避免了数据不一致的情况。
这种方案从实时性以及技术实现复杂度来说都比较不错,推荐大家使用这种方案。但是有一句话说的是没有绝对合适的技术,只有相对适合的技术,这种方案实现是也存在一些技术问题,详情见文末:方案的一些“坑”。
问题详解
1. 先写 DB 再删除缓存
先写数据库再删除缓存模式时序图如下:
读请求第一次查询时,会查询到一个错误的数据,因为写请求还没有更新到缓存,写请求写入 MySQL 成功后会删除缓存中的历史数据。后续读请求查询缓存没有值就会再请求数据库 MySQL 进行重新加载,并将正确的值放到缓存中。
2. 方案的一些“坑”
当然,这种模型也不是完全没问题,如果说恰巧读缓存失效了,就会出现这种情况。
2.1. 极端情况下的数据不一致
当缓存过期(可能是缓存正常过期也可能是 Redis 内存满了触发清理策略)条件满足,同时读请求的回写缓存 Redis 的执行周期在数据库删除之前,那么就有可能触发缓存数据库不一致问题。
上面说的两种情况,缺一不可,不过能同时满足这两种情况概率极低,低到可以忽略这种情况。
也就是说这种模型会存在一个很小周期的缓存与数据库不一致的情况,不过对于绝大多数的情况来说,是可以容忍的。除去一些电商库存、列车余票等对数据比较敏感的情况,比较适合绝大多数业务场景。
2.2. 缓存是否能删除?
再思考一个问题,缓存删除真的合适么?在涉及海量并发的场景中,如果程序删除了缓存,可能会导致缓存击穿问题,而更新频繁时则可能引发缓存雪崩。
因此,在考虑缓存一致性模型时,务必充分考虑业务场景是否属于高并发模型。如果是高并发场景,删除缓存可能并不合适,此时应采用最终一致性策略。