← All incidents

[Eval][v1][zh] Cache stampede after Redis key expiry on Black Friday morning

service: catalog-svccreated: 5/25/2026, 10:23:56 PM

Raw incident context

Time: 09:00 UTC, Black Friday. catalog-svc latency exploded at exactly 09:00:00 UTC.

Symptoms:
- catalog-svc p99: 15s (baseline 80ms)
- 503 rate: 8% (intermittent during DB overload)
- Postgres CPU: 100% sustained, lock waits climbing
- Redis CPU: 25% (looks healthy)
- Redis cache miss rate for keys matching "catalog:item:*": 95% (baseline 2%)
- All product detail page requests are flooding through to DB

Background:
- We pre-warm the homepage catalog cache every night at 02:00 UTC with TTL=7h
- 02:00 UTC + 7h = 09:00 UTC ← all keys expired simultaneously
- Black Friday traffic ramp: 12x normal at 09:00 UTC (marketing email blast)
- No per-key locking; every cache miss triggers a fresh DB query

Logs:
- 08:59:58 UTC — last cache hit logged
- 09:00:00 UTC — first wave of "cache miss + DB query" log lines
- 09:00:02 UTC — DB connection pool hits ceiling, queries start queueing

On-call:
- 09:02 — pager (multiple alerts: DBHighCPU, CatalogSvcLatencyHigh, CheckoutErrorRate)
- 09:03 — diagnosis: cache stampede confirmed by Redis miss-rate metric
- 09:05 — debating: extend TTL (won't help in flight), warm cache manually (DB is the bottleneck), or shed load

Summary

SEV1

09:00 UTC 黑五流量高峰期间,catalog-svc 因缓存雪崩导致数据库 CPU 100%、p99 延迟 15s、8% 503 错误。预热的缓存键在 09:00 同时过期,12 倍流量直接穿透至 PostgreSQL,造成连接池耗尽和锁等待。

Severity reasoning: 用户可见的页面加载失败(503 错误率 8%)、核心商品详情页延迟从 80ms 飙升至 15s,直接影响黑五营收;数据库持续过载,存在数据不一致风险。符合 SEV1 定义:用户面故障、收入影响。

deepseek-chat·prompt v1·output: zh·13176ms

Root cause hypotheses

  • high缓存键同时过期导致雪崩:所有 catalog:item:* 键 TTL 设为 7h,且预热时间 02:00 UTC,导致 09:00 UTC 全部过期,12 倍流量同时穿透至数据库。

    Evidence: Redis 缓存未命中率从 2% 飙升至 95%,日志显示 09:00:00 UTC 开始大量 'cache miss + DB query' 记录。

  • high数据库连接池耗尽:大量并发查询导致连接池满,新查询排队,进一步加剧延迟。

    Evidence: Postgres CPU 100% 持续,锁等待指标上升,连接池达到上限后查询开始排队。

  • medium黑五流量超出预期:营销邮件导致 12 倍流量,远超系统设计容量。

    Evidence: 监控显示流量在 09:00 UTC 瞬间达到 12 倍基线,与邮件发送时间吻合。

  • low数据库查询未优化:单个商品详情查询可能涉及多表 JOIN 或未使用索引,导致高 CPU。

    Evidence: 无直接证据,但高 CPU 可能由低效查询引起;需检查慢查询日志。

Investigation checklist

  1. 确认缓存雪崩范围:检查 Redis 中 catalog:item:* 键的 TTL 分布。
    redis-cli --scan --pattern 'catalog:item:*' | head -100 | xargs -I {} redis-cli ttl {}

    Expected: 大部分键 TTL 为 0 或已过期,确认雪崩。

  2. 查看数据库当前活跃查询和锁等待。
    SELECT pid, state, wait_event_type, wait_event, query_start, query FROM pg_stat_activity WHERE state != 'idle' ORDER BY query_start;

    Expected: 大量 SELECT 查询处于 active 状态,wait_event 显示 'LWLock' 或 'Lock'。

  3. 检查慢查询日志,定位耗时最长的查询。
    grep 'duration:' /var/log/postgresql/postgresql-*.log | tail -100

    Expected: 显示多个超过 10s 的查询,可能涉及 catalog 表。

  4. 确认 Redis 缓存未命中率是否仍高。
    redis-cli INFO stats | grep keyspace_misses

    Expected: keyspace_misses 持续增长,命中率低。

  5. 检查 catalog-svc 实例的 CPU 和内存。
    kubectl top pods -l app=catalog-svc

    Expected: Pod CPU 使用率接近 100%,内存正常。

Mitigation plan

  • 立即启用限流:在 API 网关或 ingress 层对 /catalog/item/* 路径实施限流,限制每秒请求数至正常峰值的 2 倍。

    Risk: 部分用户请求被拒绝,但可防止数据库崩溃。

    Rollback: 移除限流规则:kubectl delete ingress/catalog-svc-rate-limit 或回滚网关配置。

  • 手动预热缓存:编写脚本从数据库批量读取热门商品并写入 Redis,设置 TTL 为 30 分钟(避免再次同时过期)。

    Risk: 脚本本身会增加数据库负载,需在限流生效后执行,且只读取必要字段。

    Rollback: 停止脚本执行,并删除已写入的缓存键:redis-cli --scan --pattern 'catalog:item:*' | xargs redis-cli del

  • 扩展数据库连接池:临时增加 PostgreSQL 最大连接数(例如从 100 增至 200),并重启 catalog-svc 以使用更多连接。

    Risk: 过多连接可能导致数据库内存压力,需监控。

    Rollback: 恢复连接数配置并重启服务。

Customer impact

黑五期间,用户访问商品详情页时遭遇高延迟(15s)或 503 错误(约 8% 请求失败),影响购物体验和转化率。预计在缓存预热和限流生效后 10 分钟内恢复。

Postmortem draft

Postmortem: catalog-svc 缓存雪崩导致黑五故障

摘要

  • 日期:2025-01-28
  • 持续时间:09:00 - 09:30 UTC(预计)
  • 影响:商品详情页延迟 15s,503 错误率 8%,影响黑五营收
  • 严重性:SEV1

时间线

  • 09:00 UTC:缓存键同时过期,流量穿透至数据库
  • 09:02 UTC:收到告警
  • 09:03 UTC:诊断确认缓存雪崩
  • 09:05 UTC:开始限流和手动预热
  • 09:15 UTC:延迟降至 1s,503 消失

影响

  • 用户:页面加载缓慢或失败
  • 业务:黑五收入损失 X 美元

根因

  • 缓存 TTL 固定 7h,预热时间导致同时过期
  • 缺乏缓存雪崩防护(如互斥锁、随机 TTL)
  • 未对黑五流量进行压测

做得好的

  • 告警及时
  • 快速诊断

做得不好的

  • 缓存策略单一
  • 缺乏限流机制

行动项

  • [ ] 实现缓存随机 TTL(±20%)
  • [ ] 添加缓存互斥锁或回源限流
  • [ ] 黑五前进行全链路压测
  • [ ] 增加数据库连接池监控告警

Follow-ups

  • P0实现缓存键随机 TTL,避免同时过期service owner
  • P0添加缓存雪崩防护:互斥锁或回源限流(如 singleflight)service owner
  • P1黑五前进行全链路压测,模拟 12 倍流量platform team
  • P1增加数据库连接池使用率告警on-call SRE
  • P2审查 catalog-svc 数据库查询性能,优化慢查询service owner