数据库和缓存一致性如何保证的?
                           
天天向上
发布: 2025-04-20 20:09:43

原创
220 人浏览过

这是中高级研发面试中极其高频且重要的问题,它不仅考察你对缓存使用的理解,更会深挖你对数据一致性、系统设计、最终一致性策略的掌握程度。


一、简明回答(适合开场)

“数据库和缓存之间的一致性,我们采用的是先删缓存,再更新数据库,或者使用延迟双删策略来应对并发一致性问题,同时针对业务特性做了最终一致性保障。”


二、详细回答结构(专业版)

1. 为什么缓存与数据库会不一致?

因为在高并发系统中,一条数据的更新涉及两份数据副本:缓存 + 数据库。若更新过程未做好协调,就会出现:

  • 缓存数据未同步更新
  • 读取到脏数据(旧数据)
  • 缓存预热和过期策略失效

2. 常见的数据更新流程(并发安全性排序)

顺序操作流程是否推荐原因说明
❌ 更新数据库 → 更新缓存不推荐并发下容易被旧缓存覆盖新值
删除缓存 → 更新数据库推荐防止脏数据,但可能被其他请求重新加载旧数据
✅ 延迟双删策略强推荐缓解并发更新带来的回写旧值问题
✅ 先更新数据库 → 延迟删除缓存(异步或定时任务)可选保证最终一致性,适合非强一致场景

3. 延迟双删策略(推荐方式)

1. 删除缓存
2. 更新数据库
3. 延迟一段时间再次删除缓存(如500ms后)

为什么?

因为可能在步骤 2 中,有请求刚好重新将旧数据加载回缓存。第 3 步延迟删除能再次清理这些“回写脏缓存”。

示例代码(伪代码):

// 更新商品信息
await redis.Del("product:1001");          // 第一次删除
await db.UpdateProduct(1001, newData);    // 更新数据库
await Task.Delay(500);                    
await redis.Del("product:1001");          // 第二次延迟删除

4. 使用消息队列异步同步(复杂系统)

适合有中间件的架构,数据库变更后,通过 MQ 通知其他服务或缓存系统更新数据,避免强耦合。

DB 更新 → 发送 MQ 消息 → 消费者收到后更新缓存

5. 分布式锁机制(防并发污染)

在极端并发下,为了防止多个线程同时查询数据库后写入旧数据,可对 key 加分布式锁。


6. 实践策略总结(表格版)

场景推荐策略理由
缓存为读多写少延迟双删 + 缓存预热保证读效率
缓存为写频繁数据库为准 + 定时刷新缓存降低一致性维护成本
对一致性要求高分布式事务 / 消息队列 / 缓存写穿保证强一致性
用户实时数据(如余额)禁用缓存,只走数据库强一致性场景不建议缓存

三、实际项目答题模板(强烈推荐)

“我们项目中使用了 Redis 作为缓存,针对缓存与数据库一致性,我们采取的是延迟双删策略。也就是在更新数据库前先删除缓存,然后延迟一段时间再次删除缓存,避免并发时被旧数据污染。另外对于一些关键数据我们设置了数据库更新成功后发送 MQ 通知,来异步刷新缓存,进一步保障数据最终一致性。”


四、可能的追问及应答

🔹 Q:延迟删除中的“500ms”怎么来的?

这个时间基于业务性能评估、数据库写入耗时、并发量来定,一般在 200-1000ms 之间,足够覆盖大多数读写延迟。

🔹 Q:如果 Redis 挂了怎么办?

我们引入了缓存降级机制,Redis 不可用时走数据库兜底,并进行限流保护,防止数据库被打爆。


五、相关参考链接(权威)

发表回复 0

Your email address will not be published. Required fields are marked *