缓存一致性场景
2021年某电商平台的商品价格出现了一个诡异的问题:用户在App上看到的价格是99元,但下单时显示的是199元。
技术团队排查后发现:商品价格修改后,先更新了数据库,但缓存更新失败了。结果用户读取时读到的是旧价格(99元),下单时从数据库读取是新价格(199元)。
这次不一致持续了约2小时,影响了约1000个订单的金额统计,直接损失约5万元。
缓存和数据库的一致性,是分布式系统中最经典的问题之一。
【面试官手记】
缓存一致性是生产环境最常见的问题之一。我面试过的候选人里,能说清楚"Cache Aside模式"的不超过40%,能说清楚"先删缓存还是先更新数据库"的不超过20%。缓存一致性的关键是根据业务场景选择合适的模式。
一、缓存一致性的三大模式 🔴
1.1 Cache Aside
1.2 Read Through
1.3 Write Through
1.4 模式对比
二、Cache Aside详解 🔴
2.1 标准实现
2.2 先删缓存还是先更新数据库
2.3 延迟双删
三、常见问题处理 🟡
3.1 缓存删除失败
3.2 并发读问题
3.3 缓存和数据同时更新
四、一致性级别 🟡
4.1 一致性级别对比
4.2 场景选择
五、生产避坑 🟡
5.1 缓存一致性的五大坑
坑1:先更新缓存再更新数据库
坑2:缓存删除失败没有重试
坑3:缓存穿透导致击穿数据库
坑4:缓存雪崩
坑5:缓存和数据库不在同一个事务
5.2 一致性保障方案
六、真实面试回放 🟡
面试官:缓存和数据库的一致性怎么保证?
候选人(小刘):通常用Cache Aside模式。
读:先读缓存,命中返回;未命中读数据库,再写缓存。
写:先更新数据库,再删除缓存。
面试官:为什么是删除缓存,不是更新缓存?
小刘:因为删除比更新简单。
更新缓存需要把新值写入缓存,但如果写入失败,数据就不一致了。
删除缓存的话,缓存没了一定会从数据库读,下次读到的是最新值。
面试官:先更新数据库再删缓存,如果删缓存失败怎么办?
小刘:两个方案:
一是MQ消息重试。删除失败时发MQ,异步重试删除。
二是延迟双删。更新后延迟N秒再删一次,防止并发读导致的问题。
面试官:哪些数据不适合放缓存?
小刘:三类数据:
一是频繁变更的数据。缓存命中率低,不如直接读数据库。
二是强一致性要求的数据。比如余额、库存,需要强一致的直接读数据库。
三是数据量特别大的数据。缓存成本高,性价比低。
【面试官手记】
小刘这场面试的亮点:
知道Cache Aside模式
知道为什么是删除缓存不是更新
知道删除失败的处理方案
知道哪些数据不适合缓存
缓存一致性是P6工程师必备技能,能完整回答的候选人,说明有实际项目经验。
缓存一致性的核心是Cache Aside + 正确处理失败。记住三个要点:
- Cache Aside:读先查缓存,写先更库再删缓存
- 删除失败:MQ消息重试 + 延迟双删
- 一致性级别:根据业务选择强一致/最终一致
缓存一致性没有银弹,关键是理解每种方案的trade-off。