MySQL和Redis的数据一致性

10 篇文章 0 订阅
本文探讨了保证数据一致性的四种方案及其潜在问题,包括先更新数据库再更新缓存、先更新缓存再更新数据库、先删除缓存再更新数据库以及先更新数据库再删除缓存。总结指出,推荐使用先更新数据库再删除缓存的方法,但需处理数据库更新成功而缓存删除失败的情况。解决方案包括采用消息队列或Canal监听数据库变更来确保缓存的正确删除。同时,文章提到了主从同步和读写分离场景下的数据一致性挑战及解决方案。
摘要由CSDN通过智能技术生成

一、保证数据一致性的四个方案

 

  • 先更新数据库,再更新缓存(有bug)
    • 并发更新数据库场景下,会将脏数据刷新到缓存,不推荐
      • 同时有请求A和请求B进行更新操作,那么会出现:

      • 线程A更新了数据库;

      • 线程B更新了数据库;

      • 线程B更新了缓存;

      • 线程A更新了缓存;

  • 先更新缓存,再更新数据库(有bug)
    • 缓存更新成功后,数据库更新失败,则会造成数据不一致性,而且也有并发问题,不推荐
  • 先删除缓存,再更新数据库(有bug)
    • 改进方法:先删缓存,再更新数据库,再删缓存
  • 先更新数据库,再删除缓存(有bug)
    • 更新数据库成功,但是删除缓存失败。

总结:不推荐更新数据库的时候更新缓存。因为会有并发问题。推荐使用更新数据库时删除缓存,虽然也有问题。

二、 先删除缓存,后更新数据库

2.1 可能出现的问题

  1. 请求A进行写操作,删除缓存
  2. 请求B查询发现缓存不存在
  3. 请求B去数据库查询得到旧值
  4. 请求B将旧值写入缓存
  5. 请求A将新值写入数据库
  6. 如果没有给缓存设置过期时间,则缓存数据永远都是脏数据

2.2 解决方式:延时双删

  • 先淘汰缓存
  • 再写数据库
  • 休眠一秒后再次淘汰缓存,可以将1秒内所造成的缓存脏数据,再次删除!

2.3 主从同步存在的问题

对于读写分离的数据库,主从同步之间也会有时间差,若此时来了两个请求,请求A(更新操作)和请求B(查询操作),也会出现一些问题

  1. 请求A更新操作,删除缓存
  2. 请求A再主库进行更新操作,主库与从库进行数据同步操作
  3. 请求B查询操作,发现redis中没有数据
  4. 请求B去从库获取旧值数据
  5. 请求B更新缓存
  6. 主从同步完成

主从同步时间差

 解决方法:如果对redis进行填充的查询数据库操作,那么强制将其指向主库进行查询从主库中拿数据

三、 先更新数据库,后删除缓存(推荐)

3.1可能出现的问题

  • 更新数据库成功了,但是在删除缓存的阶段没有成功,则之后读取的缓存都是错误的

3.2解决方式一:异步实现之利用消息队列

  1.  请求A向服务端发送修改商品请求
  2.  相应的模块根据请求会对数据库对应内容进行更新,更新成功后会向MQ发送消息
    1. 该消息通知缓存处理模块删除对应的缓存
  3.  缓存模块监听到有新的消息,会执行缓存删除逻辑
    1.  利用消息队列的手动提交机制可以保证删除逻辑顺利完成

3.3 解决方式二:基于Canal的通知

  • 商品服务完成数据库修改操作后,业务直接结束。没有任何代码侵入
  • Canal监听mysql变化,当发现变化后,立即通知缓存服务
  • 缓存服务接收到canal通知,删除缓存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值