缓存故障时守住数据库
缓存不可用的瞬间,所有读请求都会转向数据库:数据库平时只承担少量回源流量,此时会突然面临全量并发,很容易被直接打穿,进而影响所有业务。降级方案的核心目标只有一个——限制涌向数据库的流量,让系统以可用性略降为代价继续对外服务,而不是整体雪崩。
基本信息
| 适用范围 | 以 Redis 作为缓存的读多写少业务 |
|---|---|
| 主要手段 | 本地兜底缓存、限流、熔断、返回默认值 |
| 判断信号 | 缓存超时率、错误率、回源 QPS |
| 关键动作 | 回源并发设硬上限 |
| 验证方式 | 定期模拟缓存宕机演练 |
降级准备清单
- 多级缓存:Redis 不可用时本地缓存继续服务一个短窗口
- 限流:对回源数据库的并发设置硬上限,例如信号量或令牌桶
- 熔断:错误率超过阈值后直接返回降级值,不再尝试回源
- 兜底数据:关键配置在本地保留快照,启动时即加载
- 演练:定期模拟 Redis 宕机,验证预案真实可用而不是纸面存在
降级路径示意
降级路径示意
# 读取逻辑的分层判断(伪代码)
# 1) Redis 正常 -> 走缓存返回
# 2) Redis 超时或报错 -> 读本地缓存(短 TTL)
# 3) 本地也没有 -> 限流器放行则查库,否则返回降级值
# 4) 全流程记录降级计数并告警
# 回源限流的简单实现思路:
# 信号量上限 = 数据库安全并发 / 单请求连接占用
# 超过上限直接走降级,不排队等待,避免请求堆积降级手段对照
| 手段 | 作用 | 代价 |
|---|---|---|
| 本地缓存 | 短期替代 Redis 提供读服务 | 数据可能陈旧,需短 TTL |
| 回源限流 | 保护数据库不被并发打穿 | 部分请求返回降级结果 |
| 熔断 | 错误率过高时快速失败 | 业务功能受限 |
| 默认值兜底 | 保证页面可用而非报错 | 用户看到的是非个性化内容 |
| 演练 | 提前验证预案有效性 | 需要投入测试与演练成本 |
降级的判定要快:等待缓存超时的每一毫秒都会让请求在内存中堆积,设置较短的连接与读取超时,把快速失败作为默认行为。
没有降级方案的缓存架构,等于把数据库直接暴露在缓存故障面前:预案必须落到代码与演练里,写在文档中不算数。