2. 缓存与数据库交互基础:读流程(Cache Aside)、写流程(双写/延迟双删)、常见架构图
2.1 读流程:Cache Aside Pattern(旁路缓存)
Cache Aside 是业界最经典的缓存读取策略,核心原则是“由应用程序同时管理缓存和数据库,缓存不主动加载数据”。读流程分为缓存命中与缓存未命中两种情况。
读流程核心步骤(Cache Aside):
- 读请求到达:应用程序先查询缓存(Redis)。
- 缓存命中:直接返回缓存数据,流程结束。
- 缓存未命中:应用程序查询数据库(MySQL)。
- 回写缓存:将数据库查询结果写入 Redis,并设置过期时间。
- 返回数据:将数据返回给调用方。
2.2 写流程:双写策略与延迟双删
写流程的核心挑战是“如何保证缓存与数据库的数据最终一致”。常见的写策略包括双写和延迟双删,后者是前者的增强版本。
2.2.1 双写策略(先更新数据库,再更新缓存)
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 更新数据库 | 执行 UPDATE / INSERT 语句,数据库写入成功 |
| 2 | 更新缓存 | 将新数据直接写入 Redis(SET 操作) |
⚠️ 双写策略的风险:
- 并发写冲突:线程 A 先更新数据库(值=100),线程 B 后更新数据库(值=200),但线程 B 先更新缓存(值=200),线程 A 后更新缓存(值=100)→ 缓存中残留旧值(100)。
- 适用场景:低并发、对短暂不一致容忍度较高的系统。
2.2.2 延迟双删策略(推荐方案)
延迟双删在“先更新数据库,再删除缓存”的基础上,增加一次“延迟删除”操作,以解决并发读写导致的不一致问题。
延迟双删执行步骤:
- 删除缓存:先删除 Redis 中的旧缓存。
- 更新数据库:执行数据库写入操作。
- 延迟删除:休眠一段时间(通常 100~500ms),再次删除缓存。
2.3 常见架构图:缓存与数据库交互拓扑
在实际生产环境中,Redis 缓存与 MySQL 数据库的交互通常采用分层架构,配合负载均衡、哨兵/集群等高可用组件。以下为典型的三层读写分离架构。
2.4 三种写策略对比
| 策略 | 核心操作 | 一致性保证 | 并发风险 | 推荐场景 |
|---|---|---|---|---|
| 先更新缓存,再更新数据库 | SET → UPDATE | 低(极易不一致) | 极高 | 不推荐 |
| 先更新数据库,再更新缓存(双写) | UPDATE → SET | 中(并发写可能覆盖) | 高 | 低并发、可接受短暂不一致 |
| 先更新数据库,再删除缓存(延迟双删) | DEL → UPDATE → 延迟 → DEL | 高(最终一致性) | 低 | 生产环境推荐 |
📌 测试验证要点:
- 延迟双删的“延迟时间”需要根据业务查询耗时动态调整,建议通过压测确定最优值。
- 第二次删除失败时,需要引入重试机制(如消息队列 + 异步重试),否则缓存可能永久不一致。
- 读流程中,缓存回写操作必须设置合理的过期时间(TTL),作为最终一致性的兜底手段。