并发环境下,先操作数据库还是先操作缓存?
文章插图
作者 | 捡田螺的小男孩
来源 | 捡田螺的小男孩(ID:gh_873ad5979a0b)
头图 | CSDN 下载自东方IC
文章插图
前言
在分布式系统中 , 缓存和数据库同时存在时 , 如果有写操作的时候 , 先操作数据库还是先操作缓存呢?先思考一下 , 可能会存在哪些问题 , 再往下看 。 下面我分几种方案阐述 。
github地址:
文章插图
缓存维护方案一假设有一写(线程A)一读(线程B)操作 , 先操作缓存 , 在操作数据库 。 如下流程图所示:
文章插图
1)线程A发起一个写操作 , 第一步del cache
2)线程A第二步写入新数据到DB
3)线程B发起一个读操作 , cache miss ,
4)线程B从DB获取最新数据
5)请求B同时set cache
这样看 , 没啥问题 。 我们再看第二个流程图 , 如下:
文章插图
1)线程A发起一个写操作 , 第一步del cache
2)此时线程B发起一个读操作 , cache miss
3)线程B继续读DB , 读出来一个老数据
4)然后老数据入cache
5)线程A写入了最新的数据
OK , 酱紫 , 就有问题了吧 , 老数据入到缓存了 , 每次读都是老数据啦 , 缓存与数据与数据库数据不一致 。
文章插图
缓存维护方案二双写操作 , 先操作缓存 , 在操作数据库 。
文章插图
1)线程A发起一个写操作 , 第一步set cache
2)线程A第二步写入新数据到DB
3)线程B发起一个写操作 , set cache ,
4)线程B第二步写入新数据到DB
这样看 , 也没啥问题 。, 但是有时候可能事与愿违 , 我们再看第二个流程图 , 如下:
文章插图
1)线程A发起一个写操作 , 第一步set cache
2)线程B发起一个写操作 , 第一步setcache
3)线程B写入数据库到DB
4)线程A写入数据库到DB
执行完后 , 缓存保存的是B操作后的数据 , 数据库是A操作后的数据 , 缓存和数据库数据不一致 。
文章插图
缓存维护方案三一写(线程A)一读(线程B)操作 , 先操作数据库 , 再操作缓存 。
文章插图
1)线程A发起一个写操作 , 第一步write DB
2)线程A第二步del cache
3)线程B发起一个读操作 , cache miss
4)线程B从DB获取最新数据
5)线程B同时set cache
这种方案没有明显的并发问题 , 但是有可能步骤二删除缓存失败 , 虽然概率比较小 , 优于方案一和方案二 , 平时工作中也是使用方案三 。
综上对比 , 我们一般采用方案三 , 但是有没有完美全解决方案三的弊端的方法呢?
文章插图
缓存维护方案四这个是方案三的改进方案 , 都是先操作数据库再操作缓存 , 我们来看一下流程图:
文章插图
通过数据库的binlog来异步淘汰key , 以mysql为例 可以使用阿里的canal将binlog日志采集发送到MQ队列里面 , 然后通过ACK机制 确认处理这条更新消息 , 删除缓存 , 保证数据缓存一致性 。
但是呢还有个问题 , 如果是主从数据库呢?
文章插图
缓存维护方案五主从DB问题:因为主从DB同步存在同时延时时间如果删除缓存之后 , 数据同步到备库之前已经有请求过来时 , 会从备库中读到脏数据 , 如何解决呢?解决方案如下流程图:
文章插图
文章插图
缓存维护总结综上所述 , 在分布式系统中 , 缓存和数据库同时存在时 , 如果有写操作的时候 , 先操作数据库 , 再操作缓存 。 如下:
- 推新标准建新生态,下载超198亿次金山发力海内外
- 闲鱼|电诉宝:“闲鱼”网络欺诈成用户投诉热点 Q3获“不建议下单”评级
- 王兴称美团优选目前重点是建设核心能力;苏宁旗下云网万店融资60亿元;阿里小米拟增资居然之家|8点1氪 | 美团
- 先别|用了周冬雨的照片,我会成为下一个被告?自媒体创作者先别自乱阵脚
- 丹丹|福佑卡车创始人兼CEO单丹丹:数字领航 驶向下一个十年
- 看过明年的iPhone之后,现在下手的都哭了
- 砍单|iPhone12之后,拼多多又将iPhone12Pro拉下水
- 巨头|“社区薇娅”都不够用了 一线互联网巨头全员下场卖菜
- 余额|中兴通讯:现有资金余额仅能确保公司当前经营规模下现金流安全
- 销售|Shopify宣布创下51亿美元的假日购物季销售纪录
