如何保证缓存与数据库的双写一致性
目录
- 如何保证缓存与数据库的双写一致性
- 先更新数据库,后更新缓存(不建议采用)
- 原因一(会产生缓存与数据库数据不一致):在==高并发==的场景下,如果同时有请求 `A` 和请求 `B` 进行获取数据,那么会出现
- 原因二(业务场景角度)
- 先更新缓存,后更新数据库(不建议采用)
- 先删除缓存,后更新数据库(不太理想,可以采用)
- 解决方案
- 为什么要休眠 `1` 秒钟,还要再次删除缓存
- 那么这个 `1` 秒钟是怎么确定的
- 那么采用延时双删策略,如第二次删除缓存失败怎么办
- 先更新数据库,后删除缓存(==建议采用==)
- 那么采用==延时双删策略==时,如第二次删除缓存失败怎么办
- 方案一
- 方案二
如何保证缓存与数据库的双写一致性
只要使用到缓存,无论是本地内存做缓存还是使用 redis
做缓存,那么就会存在缓存与数据库同步的问题,接下来就讨论一下关于保证缓存和数据库双写时的数据一致性
我们这里列出来所有策略,并且讨论他们优劣性
- 先更新数据库,后更新缓存(不建议采用)
- 先更新缓存,后更新数据库(不建议采用)
- 先删除缓存,后更新数据库(不太理想,可以采用)
- 先更新数据库,后删除缓存(建议采用)
先更新数据库,后更新缓存(不建议采用)
这套解决方案,大家普遍反对的,一般是没有人使用的
原因一(会产生缓存与数据库数据不一致):在高并发的场景下,如果同时有请求 A
和请求 B
进行获取数据,那么会出现
- 请求
A
更新了数据库 - 请求
B
也更新了数据库 - 请求
B
更新了缓存 - 请求
A
更新了缓存
这就出现了请求 A
更新缓存应该比请求 B
更新缓存早才对,但是因为网络等原因,B
却比 A
更早更新了缓存。这就导致了脏数据,因此不考虑
原因二(业务场景角度)
- 如果你是一个写数据库场景比较多,而读数据场景比较少的业务需求,采用这种方案就会导致,数据压根还没读到,缓存就被频繁的更新,浪费性能
- 如果你写入数据库的值,并不是直接写入缓存的,而是要经过一系列复杂的计算再写入缓存。那么,每次写入数据库后,都再次计算写入缓存的值,无疑是浪费性能的。显然,删除缓存更为适合
先更新缓存,后更新数据库(不建议采用)
这套解决方案,一般是没有人使用的。也会出现上述情况
先删除缓存,后更新数据库(不太理想,可以采用)
该方案会导致 “缓存与数据库的数据” 不一致,原因:在高并发的场景下,如果同时有一个请求 A
进行写数据操作,请求 B
进行读数据操作,那么会出现
- 请求
A
开始进行写操作,删除缓存 - 此时请求
B
开始进行读操作,发现缓存没有数据 - 然后,请求
B
去数据库查询得到数据(得到的不是请求A
写入的新数据,是旧数据,是脏数据) - 请求
B
将拿到的数据写入缓存 - 此时,请求
A
才正式进行写操作
注意:在高并发的场景下,如果同时有一个请求 A
和请求 B
都进行写数据操作,那么是不会出现缓存与数据库数据不一致的情况的
解决方案
可以采用延时双删策略,伪代码如下
public void write(String key, Object data) {// 删除缓存 redis.delKey(key);// 再写数据库 db.updateData(data);// 线程休眠 1 秒钟 Thread.sleep(1000);// 再次删除缓存redis.delKey(key);
}
为什么要休眠 1
秒钟,还要再次删除缓存
这样可以使得请求 A
在写完数据时,可以将请求 B
写入缓存的脏数据删除掉
那么这个 1
秒钟是怎么确定的
针对上面的情形,读者应该自行评估自己的项目的读数据业务逻辑的耗时,然后写数据的休眠时间则在读数据业务逻辑的耗时基础上,加几百 ms
即可。这么做的目的,就是确保读请求结束,写请求可以删除读请求造成的缓存脏数据
那么采用延时双删策略,如第二次删除缓存失败怎么办
具体解决方案,且看第四种的策略的解析
先更新数据库,后删除缓存(建议采用)
对于这种方案,在 《Cache-Aside pattern》
有提到,另外,知名社交网站 facebook
也在论文 《Scaling Memcache at Facebook》
中提出,他们用的也是先更新数据库,再删缓存的策略
那么采用延时双删策略时,如第二次删除缓存失败怎么办
提供一个保障的重试机制即可,这里给出两套方案
方案一
- 更新数据库数据
- 缓存因为种种问题删除失败
- 将需要删除的
key
发送至MQ
消息队列 - 自己消费消息,获得需要删除的
key
- 继续重试删除操作,直到成功
然而,该方案有一个缺点,对业务线代码造成大量的侵入。于是有了方案二,在方案二中,启动一个订阅程序去订阅数据库的 binlog
,获得需要操作的数据。在应用程序中,另起一段程序,获得这个订阅程序传来的信息,进行删除缓存操作
方案二
- 更新数据库数据
- 数据库会将操作信息写入
binlog
日志当中 - 订阅程序提取出所需要的数据以及
key
- 另起一段非业务代码,获得该信息
- 尝试删除缓存操作,发现删除失败
- 将这些信息发送至消息队列
- 重新从消息队列中获得该数据,重试操作
备注说明:上述的订阅 binlog
程序在 mysql
中有现成的中间件叫 canal
,可以完成订阅 binlog
日志的功能。如果对一致性要求不是很高,直接在程序中另起一个线程,每隔一段时间去重试即可,这些大家可以灵活自由发挥,只是提供一个思路
如何保证缓存与数据库的双写一致性相关推荐
- Redis面试 - 如何保证缓存与数据库的双写一致性?
Redis面试 - 如何保证缓存与数据库的双写一致性? 面试题 如何保证缓存与数据库的双写一致性? 面试官心理分析 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致 ...
- 面试:高频面试题:如何保证缓存与数据库的双写一致性?
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源 | blog.csdn.net/chang384915878 ...
- 面试必问:怎么保证缓存与数据库的双写一致性?
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 来源:https://dwz.cn/5AlJ2nWV 只要用缓存,就可能会涉及到缓存与数据库 ...
- 高频面试题:如何保证缓存与数据库的双写一致性?
分布式缓存是现在很多分布式应用中必不可少的组件,但是用到了分布式缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? Cache Aside ...
- 一个经典面试题:如何保证缓存与数据库的双写一致性?
作者:你是我的海啸 地址:https://blog.csdn.net/chang384915878/article/details/8675646 只要用缓存,就可能会涉及到缓存与数据库双存储双写,你 ...
- 阿里MySQL读写一致_阿里面试题:如何保证缓存与数据库的双写一致性?
作者:你是我的海啸 出处:https://blog.csdn.net/chang384915878/article/details/86756463 只要用缓存,就可能会涉及到缓存与数据库双存储双写, ...
- 读数据库遇到空就进行不下去_如何保证缓存与数据库的双写一致性?
作者:你是我的海啸 来源:https://blog.csdn.net/chang384915878 分布式缓存是现在很多分布式应用中必不可少的组件,但是用到了分布式缓存,就可能会涉及到缓存与数据库双存 ...
- 经典面试题:如何保证缓存与数据库的双写一致性?
作者:你是我的海啸 地址:http://t.cn/EK64FeP 只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 面试题剖析 一 ...
- 灵魂拷问:缓存与数据库的双写一致性如何保证?
原文:https://blog.csdn.net/chang384915878/article/details/86756463 转载自技术联盟之巅 分布式缓存是现在很多分布式应用中必不可少的组件,但 ...
- 如何保证缓存和数据库的双写的一致性
最初级的缓存不一致问题以及解决方案 问题: 先修改数据库,再删除缓存,如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据出现不一致 解决思路: 先删除缓存:再修改数据库,如果删除缓存 ...
最新文章
- 【控制】第九章-线性系统的状态空间描述
- P2580-于是他错误的点名开始了【Trie,字符串】
- stl之截取:以一段字符串截取字符串
- Semaphore1.8源码
- 原声php 读取excel乱码_如何解决php读取excel乱码问题
- 关于debian网卡驱动
- godot正确设置2d像素游戏
- 联想服务器怎么拆硬盘,联想ThinkStation P900工作站高清拆解
- dsp6657的helloworld例程测试-第一篇
- wind 10 安装node环境
- 厦门情侣必去浪漫的餐厅
- 计算机视觉(北邮鲁鹏)--卷积
- 粽子大战 —— 猜猜谁能赢
- 小程序swiper切换闪屏问题
- RxJava之过滤操作符
- 石家庄市学府路机动车科目三考场路线详细教案
- 【npm 报错 gyp info it worked if it ends with ok 大概率是包版本问题】
- 案例分享 | TensorFlow 在贝壳找房中的实践
- day007-列表和字典
- 基于H5 小程序 UI框架选型 2020年9月10号
热门文章
- 自动驾驶 2-1 第 1 课补充阅读:传感器和计算硬件 -- 上
- 2021-08-26BERT: Pre-training of Deep Bidirectional Transformers forLanguage Understanding
- N!阶层末尾有多少0
- Optional Interview with Benny the Irish Polyglot abo---coursera课程Learn how to learn
- pyqt5 窗口设置圆角_pyqt5-30. QWidget设置圆角,使用qss设置失败
- linux拷贝文件后几百行,我 的 一 些 练 习 题
- python编程符号大全_2020 年最值得学习的 5 大 AI 编程语言
- python的规模有多大_Python项目可以有多大?最多可以有多少行代码?
- 常问的数据结构与算法
- SSRF 服务器端请求伪造