缓存和 DB 的一致性保证(一)

本文探讨了在高并发场景下,如何通过分布式锁解决缓存与数据库间的一致性问题,介绍了弱一致性和强一致性的实现策略,并对比了Redis与Zookeeper作为分布式锁的优劣。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先看业务,业务是不是需要强一致:

弱一致:缓存设定过期时间,过期后自动从db中更新缓存;

强一致:使用分布式锁

1、线程A先对该key加上分布式锁(锁一定要设置过期时间!!!

2、线程A删除缓存

(其他线程在查询到缓存数据为空时,尝试去获取分布式锁,获取不到锁,说明有线程正在更新缓存数据,则等待锁或者直接查询数据库)

3、线程A更新数据库

4、线程A更新缓存

5、线程A解锁(如果是redis分布式锁,那么谁加的锁谁来解,使用lua先判断是不是自己加的,然后删除锁)

 

分布式锁:

1、redis:性能好,redis主从架构本身也存在数据一致性问题

2、zookeeper:大量并发情况下,性能会成为瓶颈

<think>嗯,用户这次的问题是关于缓存与数据库一致性的系统设计问题,而且特别提到了之前讨论过的Raft算法作为强一致性的解决方案。看来用户正在设计个分布式系统,需要在性能一致性之间做权衡。 从用户引用的资料来看,ta明显已经做过些调研,知道强一致性(如Raft)会牺牲性能,也了解了几种常见方案如异步双删、串行化队列等。但ta可能更希望获得系统化的分类工程实践建议,特别是如何根据业务场景选择方案。 用户引用的材料[3]提到银行场景的特殊性,这提示我需要强调业务场景对方案选择的影响。另外引用[2]提到的灰度放量监控打点很重要,这是工程实践中容易忽略的关键点。 在整理方案时,我需要特别注意: 第,避免教科书式的理论堆砌,要突出可落地的技术细节,比如重试机制具体怎么实现 第二,给用户提供决策树式的选择逻辑,比如根据业务容忍度区分方案 第三,强调监控灰度的重要性,这是线上系统稳定的关键 用户似乎对“最终一致性“强一致性”的边界还有些模糊,需要明确说明:使用缓存就意味着不可能做到实时强致,这是CAP理论的限制。Raft方案虽然能保证致,但只适合元数据管理等特定场景。 最后要注意示例的实用性,比如延时双删的代码示例要包含重试队列随机抖动,这是生产环境必备的防雪崩措施。对于金融场景的串行化方案,则要提醒吞吐量会下降到什么程度(比如从万级QPS降到千级)。</think>在分布式系统中保证缓存与数据库的一致性,本质是平衡**性能**与**数据准确性**的矛盾。以下是经过工程验证的完整方案,按一致性强度排序: --- ### 、强一致性方案(牺牲性能,保证实时致) #### 1. **Raft/Paxos强致协议** - **原理**:将缓存与数据库视为整体,通过分布式共识算法(如Raft)保证多副本强致。 - **适用场景**:金融交易、账户余额等对一致性要求极高的业务。 - **代价**:写入性能下降 30-50%(需多数节点确认)[^1]。 ```mermaid graph LR A[客户端写请求] --> B[Raft Leader] B --> C[同步复制日志到Followers] C --> D[多数节点确认后提交] D --> E[更新数据库+缓存] ``` #### 2. **串行化队列** - **原理**:所有写请求进入单线程队列,严格顺序更新数据库缓存。 - **实现**: ```python # 伪代码示例:基于Redis的串行化队列 def write_worker(): while True: task = redis_queue.pop() # 阻塞获取任务 db.update(task.data) # 先更新数据库 cache.delete(task.key) # 再删除缓存 ``` - **缺点**:吞吐量骤降(如从10k QPS降至1k QPS),仅适合低频写场景[^3]。 --- ### 二、最终一致性方案(平衡性能与一致性) #### 1. **延时双删(主流方案)** - **流程**: ```mermaid graph LR A[更新数据库] --> B[删除缓存] B --> C[延时几百毫秒] C --> D[再次删除缓存] ``` - **关键优化**: - 第二次删除异步执行,避免阻塞 - 引入重试机制(如失败3次后进入死信队列) - 延时时间 = 主从同步延迟 + 业务读耗时 #### 2. **订阅数据库变更日志(CDC)** - **原理**:监听数据库Binlog(如MySQL的canal),自动更新/删除缓存。 - **优势**: - 缓存与数据库解耦 - 支持多级缓存(如Local Cache + Redis)同步 - **工具**:Debezium, Alibaba Canal, Kafka Connect #### 3. **设置合理的缓存过期时间** - **兜底策略**:所有缓存设置TTL(如30秒),即使出现不致,也会在过期后自动修复。 - **注意**:需结合业务容忍度设定(如商品详情页可容忍10秒不致)。 --- ### 三、工程实践关键点 1. **监控与巡检** - 对比DB缓存的数据差异(抽样率≥0.1%) - 不致率>0.01%时触发告警[^2] ```bash # 伪代码:定时巡检脚本 while True: db_data = query_db("SELECT * FROM products WHERE id=1001") cache_data = redis.get("product:1001") if db_data != cache_data: send_alert("数据不致!") sleep(60) # 每分钟检查次 ``` 2. **灰度发布与流量控制** - 新策略先作用于5%的流量,验证一致性问题 - 通过限流(如Sentinel)避免缓存雪崩 3. **缓存降级策略** - 当DB压力过大时,短暂允许脏数据 - 记录日志,事后补偿修复 --- ### 四、方案选择决策树 ```mermaid graph TD A[业务需要强一致性?] -->|是| B[使用Raft/串行化队列] A -->|否| C{读多写少?} C -->|是| D[延时双删+TTL兜底] C -->|否| E[CDC日志同步] ``` > **关键结论**: > - 99%场景选择**延时双删+TTL**即可满足需求 > - 强一致性方案仅用于核心金融业务 > - 监控比算法本身更重要[^2][^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值