redis与DB的一致性7种策略
- IT业界
- 2025-09-12 17:06:01

为什么要使用 redis 做缓存?封底估算为什么是单行数据的QPS,而不是总的? 什么时候使用DB,Redis,本地缓存 数据的分类一致性的方案1. 先清除Redis,再更新 DB2. 先更新DB,再清除 Redis使用场景: 3. 延迟删除与延迟双删使用场景 4. 监听 binlog 清除5. 双写使用场景: 6. 监听binlog更新7.定时刷新使用场景 选择其他问题缓存穿透 为什么要使用 redis 做缓存?
高性能
redis压力测试: 20w QPS(瓶颈是网络 io)MySQL: 2w QPS(瓶颈是磁盘io) 封底估算是否使用缓存是有单行数据的 QPS 决定的
为什么是单行数据的QPS,而不是总的? 使用(Redis)缓存主要是利用 缓存( Redis)高性能的特性减少DB的重复查询就是数据需要多次查询,并且每次查询的结果是相同的,这时候加到缓存中,可以拦截大量的请求在缓存层,减少db的请求压力 举个例子一些 IM 系统的总的 QPS 有几十万(qq,wx 这些)但是每个人接受的消息是不同的,并且消息是一次性消费的,所以针对单行消息而言,QPS 是小于 1 的并且是一次性消费,不涉及多次重复查询,即使总的 QPS 非常高,也不会使用缓存(IM 系统会使用Redis,但是不是做缓存使用的) 什么时候使用DB,Redis,本地缓存使用 DB
当数据是部分人可见的(比如后台管理/GM 的需求):单行数据的QPS<1(是一个常数)使用Redis 缓存
数据所有用户可见,单行数据的QPS>1 ,就需要考虑 Redis 缓存了本地缓存
原因 Redis 有 20 万 QPS,但是单 key 的 QPS 只有几千;而本地内存的读写性能有千万(map 读写)所以当单行数据的 QPS>5000(参考阿里云的热 key 二级缓存标准 QPS) 就可以考虑使用本地缓存了 数据的分类 热数据: 考虑极端热数据的情景(1w 的 QPS)冷数据: 0 QPS(没人访问)由冷数据突然变成热数据: QPS 0 突变-> QPS 2000我们的核心要求是:
热数据不能失效,因为热数据失效容易造成缓存击穿的问题冷数据不能长时间储存在缓存(redis)中: 控制成本冷数据(没有缓存)突变到热数据(大量请求): 不能全部请求都回源(查询 DB),否则会造成缓存击穿问题 一致性的方案 1. 先清除Redis,再更新 DB 存在的问题: 间隙查询的不一致问题有缓存击穿的风险举个例子:
不一致 再清除 Redis 后,更新 DB 前有一个查询请求因为 DB 没有更新,查询请求查询到旧数据,然后将旧数据更新到 Redis这时 Redis 中的就是一条脏数据,造成数据不一致的问题 如果清除到一条有 1万 QPS 的 key 很容易发生击穿的问题 2. 先更新DB,再清除 Redis 存在的问题: 缓存击穿的问题还是清除到 1 万 QPS 的 key 很容易发生击穿
使用场景: QPS不高(单行数据QPS<20,不存在热key 的场景)的非核心业务:比如用户的主页 3. 延迟删除与延迟双删工作流程: 先更新 DB,再等一段时间清除 Redis / 先清除 Redis,再更新 DB,再等一段时间清除 Redis
核心解决的问题: 查询从库导致的数据不一致的问题
举个例子:
更新 DB 是更新的主库,从库需要一段时间进行同步但是 DB更新完后,从库没有同步好,这时有一个查询,查询到有个未同步的从库(旧数据)然后将数据更新到 Redis所以延迟的作用就是等待从库的数据同步好,保证数据一直
延迟多久?
具体要根据项目中的同步的耗时与单行数据的 qps来确定是否需要延迟删除/延迟双删 使用场景 QPS不高(单行数据QPS<20,不存在热key 的场景)的非核心业务:比如用户的主页 (本质与方案 2 是相同的,不能有热 key; 只是增加了延迟解决从库查询的不一致问题) 4. 监听 binlog 清除解决的问题:
将自当成 DB 的一个从节点,监听主节点的 binlog,并删除Redis服务解耦和: 与之前不同的是这种方案是低耦合实现问题:
同样只适用于 QPS<20(没有热 key 问题的需求)实现复杂: 监听 binlog 的逻辑是比较复杂的(比如 binlog 的获取,解析,消费等) 5. 双写工作流程: 先更新 DB,再更新 Redis
存在的问题与解决方案 并发写的不一致问题 举个例子: 有两个写请求(请求 1,将数据改为 A; 请求 2 将数据改为 B)这时请求 1 先执行,将DB 改为 A,然后请求 1 阻塞请求 2 后执行,先将 DB 改成 B , 再将 Redis 改成 B这时请求 1 阻塞恢复了,将 Redis 改成 A这时 DB 是 B,Redis(缓存)是 A,造成了一个数据不一致的问题 解决方案: 加分布式锁,不允许同时更改,只能一个执行完成才能执行下一个 使用场景:完善一下
热数据的过期失效问题(自动续期)冷数据突变为热数据(只放一个请求回源更新,其他请求返回空)完善后可以适用于高读,高写,高一致性的场景: 比如抢红包业务
抢红包业务分析:
红包发出会有大量的抢红包的操作,就涉及到大量的写(并发写)红包发出有大量的人查询抢红包的记录: 大量读抢完红包后需要所有人看到最新的记录: 高的一致性 6. 监听binlog更新核心解决的问题
binlog 是有序的,如果能顺序消费 binlog 就可以解决双写中并发写的问题如何订阅 binlog?
使用Canal组件(原理就是伪装成从节点向主节点发送 dump)缺点:
复杂,binlog 的获取,解析,消费整套是比较复杂的逻辑(比锁实现起来要更复杂),并且还要考虑过期失效的问题与冷数据突变为热数据的问题一致性没有双写好(双写使用了分布式锁,基本就是一个强一致的方案) 7.定时刷新实现方式:
储存(Redis)缓存的时候储存一个数据的更新标记(val 是一个空值),并且 更新标记的过期时间<数据的过期时间
比如:更新标记 10s 过期; 数据 10 分钟过期查询的时候先使用 set nx px 命令检查更新标记是否存在,
如果存在(写失败): 就使用 Redis 的数据如果不存在(写成功): 就回源(查询 DB)更新 Redis(更新数据与过期时间)如此就可以实现数据的定时刷新(每个更新标记的存活时间刷新一次),这样可以解决一致性的问题与热数据过期失效的问题,一举两得
解决完热数据的问题还剩冷数据与冷数据突变为热数据
冷数据: 不使用会自动过期,释放空间冷数据突变为热数据: 第一个会回源(set nx 成功),其他请求暂时返回空,知道回源完成为什么是返回空而不是回源或者阻塞?
回源的问题: 击穿阻塞的问题: 阻塞大量的请求(协程)(假设有 1万 QPS,回源需要 10s,就会阻塞 10 万个请求)优点:
实现简单: 定时刷新同时解决了一致性问题与热数据的失效问题好拓展: 不仅适用于 Redis 与 DB 的一致性,还适用于内存与 Redis 的一致性 使用场景 一致性要求不高(不敏感): 比如要求是更新后 10 分钟内可以看到数据最新的状态读高: 有大量读并存在热点问题比如: 短视频平台的视频数据
选择 封顶估算: 对单行数据进行封顶估算决定是否使用缓存,使用什么缓存任务分解: 将实际需求中可能遇到的情况罗列出来(比如:热数据,冷数据,冷数据突变为热数据)分析每一种情况,并提供对应的解决方案.参考: blog.csdn.net/weixin_42338901/article/details/129231758
其他问题上面主要解决的是击穿问题,Redis 缓存的常见的三大问题还有两个
缓存穿透: 使用不存在的 key 进行访问缓存雪崩: 缓存大面积失效 缓存穿透常见的解决方案:
布隆过滤器 实现: 多次哈希,然后标记对应的 bit 位(变为 1) 判断是否出现过: 多次哈希,所有 bit 位都为 1 才算问题:
不是 100% 准确的,存在误判的可能只能记录是否出现过(适合做加法,很难做减法) 举个例子: 某个 key 开始是不存在的,加到布隆过滤器中防止穿透,后面存在了;这时候别人访问这个 key 就会拦截掉. 记录空值 相同的不存在的 key 重复访问会拦截到 Redis 层缺点: 比布隆过滤器消耗空间更大
redis与DB的一致性7种策略由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“redis与DB的一致性7种策略”