缓存和数据库不一致问题

在高并发场景下,为了减轻数据库压力,引入缓存可能导致数据不一致。文章探讨了四种更新策略:先更新数据库再更新缓存、先更新缓存再更新数据库、先删除缓存再更新数据库、先更新数据库再删除缓存,以及各自的问题和解决方案,包括使用分布式锁、设置缓存过期时间、延迟双删和利用MySQLbinlog确保数据一致性。
摘要由CSDN通过智能技术生成

1.什么情况下会产生缓存和数据库不一致的情况

在高并发情况下,往往会极其频繁的去操作数据库,当请求量大了之后,数据库就会扛不住,挂了,这时我们会引入缓存,将部门数据放在缓存中,减少数据库的压力。
这就意味着我们读取数据可以从两个地方读取,那必然会导致数据不一致的情况。

2.如何去更新缓存和数据库

大致有四种方法

  • 先更新数据库,在更新缓存
  • 先更新缓存,在更新数据库
  • 先删除缓存,在更新数据库
  • 先更新数据库,在删除缓存

2.1 先更新数据库,在更新缓存

产生数据不一致
在这里插片描述
产生原因
更新数据库和更新缓存都是两个独立的操作,没有对操作做并发控制,那么在并发下,写入缓存和数据的顺写就可能会发生变化,导致数据不一致。

解决方法

  1. 加锁,在更新缓存前加一个分布式锁,保证同一时间内只有一个请求可以更新缓存。(缺点:加锁必然会影响数据写入的性能)
  2. 给缓存加过期时间,在更新缓存后,给缓存加一个较短的过期时间,出现数据不一致,也可以很快的更新。(缺点:还是会出现数据不一致的情况,具体看业务场景是否允许)

2.2 先更新缓存,在更新数据库

产生数据不一致
在这里插入图片描述
产生原因(和2.1一样)
更新数据库和更新缓存都是两个独立的操作,没有对操作做并发控制,那么在并发下,写入缓存和数据的顺写就可能会发生变化,导致数据不一致。

解决方法(和2.1一样)

  1. 加锁,在更新缓存前加一个分布式锁,保证同一时间内只有一个请求可以更新缓存。(缺点:加锁必然会影响数据写入的性能)
  2. 给缓存加过期时间,在更新缓存后,给缓存加一个较短的过期时间,出现数据不一致,也可以很快的更新。(缺点:还是会出现数据不一致的情况,具体看业务场景是否允许)

2.3 先删除缓存,在更新数据库

产生数据不一致
在这里插入图片描述
解决方法
延迟双删,先删除缓存,在更新数据库,延迟一段时间,再删除缓存
注意:
延迟一段时间,这个时间必须大于一次写入操作的时间
延迟多长时间具体看调试而定,极端情况下还是会出现数据不一致

2.4 先更新数据库,在删除缓存(推荐)

产生数据不一致
在这里插入图片描述
推荐原因
实际中,这个问题出现的概率并不高。因为缓存的写入通常要远远快于数据库的写入,所以在实际中很难出现请求 B 已经更新了数据库并且删除了缓存,请求 A 才更新完缓存的情况。所以,「先更新数据库 + 再删除缓存」的方案,是可以保证数据一致性的。
解决方法

  1. 加入缓存过期时间
  2. 加入缓存过期时间,在异步操作缓存(重试机制和订阅mysql binlog)
    重试机制(删除失败重试删除)
    借助消息队列完成,把删除缓存放入到消息队列,由消费者完成删除缓存操作
    如果第一次删除缓存失败,消息队列重新读取数据,进行删除;
    删除成功,就把数据移除消息队列。
    订阅 MySQL binlog,再操作缓存
    只要更新数据库成功,就会产生一条变更日志,记录在 binlog 里。
    于是我们就可以通过订阅 binlog 日志,拿到具体要操作的数据,然后再执行缓存删除,阿里巴巴开源的 Canal 中间件就是基于这个实现的。
    Canal 模拟 MySQL 主从复制的交互协议,把自己伪装成一个 MySQL 的从节点,向 MySQL 主节点发送 dump 请求,MySQL 收到请求后,就会开始推送 Binlog 给 Canal,Canal 解析 Binlog 字节流之后,转换为便于读取的结构化数据,供下游程序订阅使用。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值