-
什么是缓存?
缓存就是数据交换的缓冲区(称作Cache [ kæʃ ] ),是存贮数据的临时地方,一般读写性能较高。
根据 id 查询商铺缓存
🔍 数据一致性问题的本质
缓存与数据库数据不同步
核心:更新数据库时,如何同步更新缓存?
常见的缓存更新策略:
🧠 缓存更新策略分类
一、被动更新(自动/半自动)
-
内存淘汰机制(全自动)
Redis 内存不足时,自动根据策略淘汰缓存数据:noeviction:不淘汰,返回错误allkeys-lru:所有键中淘汰最久未使用的allkeys-random:所有键中随机淘汰volatile-lru/random/ttl:仅从设置了过期时间的键中淘汰
-
超时剔除(半自动)
为缓存设置 TTL,到期自动删除。
二、主动更新(手动编码)
1. 双写方案(Cache Aside Pattern)
推荐模式:读时查缓存、写时更新数据库 + 删除缓存
写操作流程:
- ✅ 先更新数据库,再删除缓存(推荐)
- ❌ 先删缓存,再更新数据库 → 容易导致缓存击穿
注意:
- 出现脏读概率低,优于缓存击穿
- 适用于单体系统:操作放同一事务
- 分布式场景可结合 TCC事务机制
2. 读写穿透方案(Read/Write Through)
- 读:未命中缓存 → 从数据库查 → 回写缓存
- 写:先写缓存 → 缓存再同步写数据库
- ✅ 一致性好,调用方无感知
- ❌ 实现复杂,维护成本高
3. 写回方案(Write Behind)
- 读:缓存未命中才访问数据库
- 写:只写缓存 → 异步或批量刷入数据库
- ✅ 写性能高
- ❌ 一致性差、风险大
- ❌ 数据实时性低
📌 不同方案对比与适用场景
| 策略 | 一致性 | 性能 | 实现难度 | 适用场景 |
|---|---|---|---|---|
| 双写方案 | 中 | 中 | 低 | 读多写少,业务代码可控制一致性 |
| 读写穿透方案 | 高 | 中 | 高 | 对一致性要求高,数据实时性强 |
| 写回方案 | 低 | 高 | 中 | 写多读少,对实时性要求不高 |
| 内存淘汰+TTL | 低 | 高 | 低 | 一致性要求不高的场景,如类目缓存 |
✅ 实践建议
-
高一致性场景:采用主动更新策略 + TTL兜底
如:店铺详情、用户信息
-
低一致性场景:采用内存淘汰 + TTL
如:分类列表、热门推荐等