mysql高并发下保持一致性_高并发下数据库和缓存一致性的保证

原标题:高并发下数据库和缓存一致性的保证

对于缓存的使用,从理论上来说,既然想要使用缓存就肯定存在数据在极短时间内的不一致性,如果追求极强一致性,例如下单商品的价格之类是不可以采用获取缓存的方式,所以在缓存的架构中更多是寻找一种最终一致性的解决方案,对应不同的应用场景也需要寻找不同的解决方案。

大致网上会有几种简单的方案:

1.先更新缓存,后更新数据库

2.先更新数据库,后更新缓存

3.先删除缓存,后更新数据库

4.先更新数据库,后删除缓存

5.先删除缓存,后更新数据库,再删除缓存

1.先更新缓存,后更新数据库

这种策略纯属凑数,应该没人会这么使用

2.先更新数据库,后更新缓存

这种策略存在最大的问题是多线程导致出现的脏数据

T1线程先更新了数据库 —> T2线程再更新数据库 -> T2线程更新了缓存 -> T1线程更新了缓存

此时DB中的数据是T2线程更新的数据,但缓存中确实T1线程更新的缓存,出现了数据库和缓存的不一致

另外还存在一种问题就是,如果写的几率比读的几率大,那每次写的线程,还需要额外承担输入缓存的业务,从性能上来看得不偿失。

3.先删除缓存,后更新数据库

也是在多线程中可能导致脏数据

T1写线程删除缓存 -> T2读线程获取不到缓存 -> T2读线程重新从DB构建缓存 -> T1更新DB

此时DB中的数据是T1写线程更新的数据,而缓存中的数据是T2读线程在T1提交之前构建的数据,出现数据库和缓存不一致性

解决这个问题可以让T1写进程,再更新DB后,再删除一次缓存,这个其实是双删策略,其实就是第5条

4.先更新数据库,后删除缓存

此策略是让读线程从缓存中获取,如果缓存不存在或失效,从db获取,然后再写回去缓存。

T1写线程直接更新DB,然后删除掉缓存,如果现在有三个线程 T1写 T2写 T3读

T1写写成更新DB -> T1删除缓存 -> T3读线程获取不到缓存,读取DB获取数据 -> T2写线程更新DB -> T2删除缓存 -> T3把获取到的数据写回缓存

此时DB的数据是T2更新的数据,而缓存确实T3在T2更新DB前从DB获取的数据,出现数据库和缓存不一致,不过这是一种理论的存在,这种理论在于T3很快获取DB数据,而又很慢的会写缓存,这种理论却是是存在的,不过可以说几率确实比前面2种小的多得多

如果非得解决有几种解决的思路

T2写线程更新完DB,可以稍等下去删除缓存,不过这是不可靠的

减少缓存有效期,用缓存失效来达到最终一致性,(在考虑到极低的概率出现不一致性的问题,其实这是最低成本也是最方便的解决方案,当然根据业务而定)

此处还存在另一个问题,网上有人提出,就是第一步操作成功,第二部操作失败,这个其实是分布式中的分布式事务常常出现的问题,也是根据业务而定

删除缓存可以通过 1。线程自身判断,重复尝试 2.把删除失败交付给队列,让另外一个队列机制去尽最大努力尝试 3.抛出异常流,实施报警,让人为介入。

另外还有一种是阿里的canal,是直接订阅mysql的binlog到相对的缓存或者nosql中去,并没有使用过。

陈于喆

http://www.icoco.tech/高并发下数据库和缓存一致性的保证/返回搜狐,查看更多

责任编辑:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值