如何保证mysql和redis数据一致性的问题,即缓存更新策略

问题是什么

现在的后台架构中,经常使用redis作为缓存,使用mysql作为数据库,以实现更加高效的读写。然而在高并发的情况下,有时会出现redis和mysql数据不一致的情况,例如数据已经更新到了mysql数据库,缓存中读取到的仍然是旧数据。
为了缓解这种情况的出现,我们要针对不同的场景设计不通的缓存策略,例如读多写少的场景,读少写多的场景,对数据一致性要求高的场景,对时效性要求高的场景等,没有一个能够以一敌万的策略,只有更加合适,出错率更低的策略。

三种常用的缓存读写策略

旁路缓存模式策略、读写穿透策略、异步缓存写入策略。

旁路缓存策略(实际使用最多)

策略是什么

写数据:

  1. 直接写入DB,然后删除缓存

读数据:

  1. 如果缓存命中,直接返回结果。
  2. 缓存没有命中,则读取DB,更新缓存,返回结果。

先更新DB,再删除Cache,或者先删除Cache,再更新DB都会有问题

如果先删除cache,再更新DB,可能会造成缓存和DB的数据不一致,例如:

写请求读请求读请求
删除Cache数据A
查询Cache数据A不存在
从DB读取数据A
更新数据A到Cache
更新数据B到DB
查询Cache数据,读取到A

当多个请求并发时,写请求1的两个操作之间穿插了请求2的所有操作(主要是写DB比较慢,需要分配更多的时间片才能执行完成),导致Cache的数据没有正确更新。只有等下次更新或者缓存自动过期后才会把最新的数据B存入缓存,如果是更新则有可能再次发生这样的问题,导致一直不一致…

如果先更新DB,再删除Cache,还是可能会造成缓存和DB的数据不一致,例如:

读请求写请求读请求
查询Cache,不存在
从DB读取数据A
更新数据B到DB
删除Cache数据A
更新数据A到Cache
查询Cache,读取到数据A

同样可能由于线程调度等原因,读请求 1 的更新Cache操作晚于写请求 2 中的删除Cache操作,这样会导致最终写入缓存中的是来自请求 1 的旧值A,而写入数据库中的是来自请求 2 的新值B,即缓存数据落后于数据库,此时再有读请求 3 命中缓存,读取到的便是旧值A。

先更新DB,再删除缓存,和先删除缓存,再更新DB的方式,在多并发的情况下都会出现缓存和数据库中的值不一致的情况。

但是在先更新DB,再删除缓存的情况下,这种场景出现的概率要小许多,因为更新DB所需的线程调度时间要远大于更新Cache,所以一般情况下都是读请求更新Cache先执行完成,之后写请求会执行删除Cache的操作,后续的读请求读到的就会是真实数据了。所以这两种方法相比来说,还是先更新DB,再删除Cache比较好一点。

针对先删除缓存,再更新DB的方法,可以采用延迟双删的方法:即之前的步骤完成后,睡眠一段时间,再删除一次缓存。但是具体睡眠多久其实是个玄学,很难评估出来。

思考二、为什么是删除Cache,可以更新吗

这里主要考虑一个性能问题,缓存的更新可能成本很高,例如设计多表联合计算,复杂运算等,在写频繁的时候性能会下降严重。

缺点

  1. 首次请求的数据一定不在cache中,这样对于一些新上的热点数据,就会对数据库造成比较大的压力,甚至冲坏数据库。对于这种情况,我们可以将热点数据提前写入cache中。
  2. 写操作比较频繁的时候,cache中的数据被频繁的删除,这样会影响缓存的命中率。对于这种情况,说明这种方法可能不太适合,应该及时调整架构,更换缓存策略。

读写穿透策略

策略是什么

写数据:

  1. 先查cache,cache中不存在,cache provider服务直接更新db;
  2. 先查cache,cache中存在,cache providr服务同时更新db和缓存;

读数据:

  1. 先查cache,命中直接返回;
  2. 先查cache,没有命中,则从DB加载到cache中,再返回响应;

这种方式适用于对缓存命中要求高的业务;
但是这种方案也会在高并发的情况下出现数据不一致的情况,针对这个问题提出两种解决方案:

  1. 更新缓存之前加一个分布式锁,但是会对性能造成一定的影响
  2. 在更新完缓存之后,给其加较短的过期时间;这样即使出现数据不一致的情况,时间也比较短;

异步缓存写入

写数据:

  1. 直接将数据写入缓存
  2. 通过批量异步的方式,按照一定策略定期更新数据库;

读数据:

  1. 先查cache,命中直接返回;
  2. 先查cache,没有命中,则从DB加载到cache中,再返回响应;

这种方式下,缓存和数据库的一致性不强,对一致性要求高的系统要谨慎使用。但是它适合频繁写的场景,MySQL的InnoDB Buffer Pool机制就使用到这种模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值