到底要不要延迟双删?

2,817 阅读3分钟

前言

延迟双删,面试的时候大家应该都回答过这个答案吧?之前总有公司喜欢问,redis和mysql数据库的双写一致性怎么保证?今天就深究一下,实际开发中到底要不要延迟双删。

问题原因

只要用到缓存,无论是什么缓存方式,都会存在数据同步不一致的问题。

1726295643854.png

如图:

  1. 先读取缓存,缓存数据存在,就返回结果
  2. 如果缓存数据不存在,就读数据库
  3. 读完数据库,同步数据库数据到缓存中

但是在高并发的场景下,当数据库的数据变动后,还没来得及更新缓存数据时,这段真空期内的其他请求读到的都是变更前的数据,这就是数据库的数据和缓存中数据的不一致。

CAP理论:一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项

缓存的使用提供了可用性和容错性,在一致性上就有不足,无论什么方案,都只能降低数据不一致发生的概率。

解决方案

方案一:先修改数据库,再删除缓存

1726297073444.png

如图:

  1. 请求A,先去更改数据库,再删除缓存(在这之间存在真空期)
  2. 真空期内,请求B请求脏数据缓存
  3. 请求C,访问缓存,缓存不存在,查询数据库,返回结果并回填缓存

方案二:先删除缓存,再修改数据库

1726301382863.png

如图:

  1. 请求A,先删除缓存,再去更改数据库
  2. 在删除缓存后,更改数据库之前,请求B查询缓存,未查询,则访问数据库,同时回填缓存
  3. 请求C,访问缓存,缓存存在,但是查询到的是请求B的缓存脏数据

方案三:延迟双删

无论是先删缓存还是先删数据库,都有情况能造成缓存的不一致。

延迟双删,就是在操作后,延迟一个写的时间,再去删除缓存,这个延迟操作就是为了确保数据库和缓存的最终一致性。

image.png

延迟双删是先删除缓存还是后删缓存都可以,各有优缺点。先删除缓存的话,在修改数据库之前的其他请求都会打到数据库上,造成数据库压力,先删除数据库的话,删除缓存之前的数据就会存在一部分脏数据。

总结

一般业务选择方案一就可以了,如果强一致的业务比如秒杀或者库存业务就需要选择其他方案,选择延迟双删也是为了保证最终一致性,但是也存在读到脏数据的可能。

如果是秒杀减库存业务,可以将数据库的读写操作交给消息队列去处理,及时把缓存修改先,后面再去保证一致性,因为是读多写少的场景,缓存能获得巨大的收益。