为了提高查询的效率,我们经常会用到redis缓存,但是使用redis缓存就不可避免缓存一致性的问题。
先删缓存,再更新数据
如果并发查询可能会再删除缓存后,还没有更新数据库的时候,第二个线程读取到旧数据,并将旧数据写入缓存,导致数据不一致。
先修改数据,再更新缓存
问题1:如果先修改数据,再更新缓存,如果此时有并发查询,则第二个线程在修改数据和更新缓存之间查询的时候,查询到的数据是旧数据,导致数据不一致。
问题2:如果先修改数据,再更新缓存,如果此时修改数据成功,但是更新缓存失败,则会导致后面查询到的数据是旧数据,导致数据不一致。
双删除
先删除缓存再更新数据再删除缓存
此时可以解决先修改数据,再更新缓存多线程读取到旧数据的问题,但还不能完全解决缓存一致性问题。
并发情况下如果第二个线程查询到旧数据后,在第一个线程第二次删除缓存后再更新缓存,则会导致后面查询到的数据是旧数据,导致数据不一致。
所以此时需要引入延迟双删除。
延迟双删除
延迟双删除要求延迟删除的时间要大于一次查询和更新缓存的时间。原因:如果延迟时间小于这的时间,会导致第一次请求清除了缓存,之后第二次请求将查询到的旧数据写入缓存,造成数据不一致。
延迟双删除的策略:
异步线程
如果是单机系统可以考虑使用异步线程,延迟几百毫秒到2秒之间(根据自己接口的耗时判断),此种策略只适用于请求量不大的情况下,如果服务器重启,则延迟删除的任务会丢失,不推荐。
延迟mq
发送删除redis的延迟mq,如果删除失败还可以重试。适合分布式架构,并发多的业务。
延迟双删除也不能避免数据不一致,所以redis的缓存时间也不要太久,便于及时更新缓存信息。