前言
延时双删(Delayed Double Deletion)是一种在分布式系统或缓存一致性处理中使用的技术,目的是确保缓存与数据库之间的数据一致性。它主要用于处理在高并发情况下,缓存和数据库可能出现的数据不一致问题。
常见更新策略的问题
简单的先删缓存再更新数据库或者先删除数据库再更新缓存都是有问题的。
先删缓存,再更新数据库
先说下这种操作可能出现的问题:
- 线程A删除缓存数据,此时还没更新数据库;
- 线程B查询缓存没有数据,查询数据库读到旧数据,然后放入缓存;
- 线程C及后续线程读到缓存中的旧数据,造成缓存和数据库不一致。
先更新数据库,再删除缓存
这种方式还是比较常用,但是会造成短暂时间内数据库和缓存数据不一致,删除缓存操作比较快,这种情况下是可以接受。
- 线程A更新数据库,此时还没有删除缓存;
- 在线程A删除缓存之前,线程B及其他线程此时使用的是缓存中就旧数据,和数据库内容不一致。
- 极端情况下,在更新数据库之前缓存过期,C线程读了数据库旧数据,然后在A线程删除缓存之后才写入缓存,这种会造成后续的不一致,但是这种情况发生概念很低,还是要优于先删缓存,再更新数据库的情况。
延迟双删
针对以上情况,出现了延迟双删这种策略,但是又出现了两种常见方式,即:
- 先删缓存,再更新数据库,延迟一段时间再删一次缓存;
- 先更新数据库,再删缓存,延迟一段时间后再删一次缓存。
在讨论延时双删的两种不同实现方式时,需要考虑并发情况下的各种问题和风险。以下是对这两种方法的详细比较和分析:
先删缓存,再更新数据库,延迟一段时间后再删一次缓存
这种策略实现步骤如下:
- 删除缓存。
- 更新数据库。
- 延迟一段时间后再次删除缓存。
并发问题分析
可能出现的情况:
- 在删除缓存和更新数据库之间,读请求可能会访问到旧的数据,再次删除缓存之前的几秒内读到的都是脏数据。
- 极端情况下,在删除缓存和更新数据库之间查到旧值的线程,在再删缓存之后才更新到缓存之中,造成后续的请求读缓存和数据库不一致。
优点
- 操作简单,直接删除缓存和更新数据库,逻辑清晰。
缺点
- 在高并发场景下,不容易保证缓存和数据库的一致性,容易出现数据不一致的问题。
先更新数据库,再删缓存,延迟一段时间后再删一次缓存
这种策略实现步骤如下:
- 更新数据库。
- 删除缓存。
- 延迟一段时间后再次删除缓存。
并发问题分析
可能出现的情况:
- 更新数据库后,如果在删除缓存之前有读请求过来,这些请求会读到旧的缓存数据,但最终会被延迟的删除操作清除。
- 如果在更新数据库之前缓存过期,C线程读数据库旧数据,并在极端情况下在A线程延迟删缓存之后才覆盖缓存,后续请求读缓存和数据库不一致,不过这种情况发生概率极,合理设置延迟时间会让这种情况发生概率更低。
优点
- 更容易保证数据一致性。即使在更新数据库后有并发写操作,延迟删除缓存可以最终确保缓存中的数据是一致的。
缺点
- 可能会增加数据库的压力,因为在缓存删除和重新加载期间,所有读请求都会直接访问数据库。
总结
由上述分析,第二种延迟双删(先更新数据库,再删缓存,延迟一段时间后再删一次缓存)在高并发场景下更为安全和可靠。