🛒

电商大促场景下,如何设计 Redis 架构?

高并发、热点数据、高可用三大挑战 — 预防 + 容错 + 优化,一图一动画讲透

缓存预热 热点数据 集群高可用 性能优化 熔断降级 监控告警
① 架构总览 ② 缓存预热 ③ 热点数据 ④ 集群高可用 ⑤ 性能优化 ⑥ 熔断降级 ⑦ 监控告警 ⑧ 测一测
总 架构总览 — 大促 Redis 全景图
大促架构的核心公式:预防(预热 + 本地缓存) + 容错(集群 + 熔断) + 优化(Pipeline + 拆 Key) = 撑住百万 QPS
1 缓存预热 — 大促前把数据搬进 Redis
核心思想:大促开始前,提前将热点商品数据批量写入 Redis。若不预热,大量请求会在活动瞬间穿透到数据库,造成雪崩。

🌡️ 为什么需要预热?

  • 冷启动时 Redis 命中率为 0,所有请求打到 DB
  • DB 瞬时压力是平时的 10~100 倍,极易宕机
  • 预热后命中率可达 95%+

📋 预热策略

  • 提前 1~2h 跑预热脚本,批量 SET 热点商品
  • 按历史访问量排序,优先预热 Top N
  • 分批次预热,避免 Redis 瞬时写压力
  • 设置合理 TTL,活动结束自动失效
2 热点数据处理 — 三把刀

🔪 刀1:拆分热点 Key

大 Key 请求全打到同一个 Redis 节点,单节点成瓶颈。

rank:hot → rank:1 ~ rank:N

读时随机选一个分片,写时广播更新所有分片

🛡️ 刀2:本地缓存

应用层加 Guava Cache / Caffeine,热点数据缓存在 JVM 内存。

访问链路:本地缓存 → Redis → DB,大幅减少 Redis QPS

🔒 刀3:互斥锁

热点 Key 更新时,用 SETNX 加锁,只让一个线程去更新缓存,其余等待或返回旧值。

避免缓存击穿(Key 过期瞬间大量请求打 DB)

🔥 热点 Key 拆分演示

点击 Key 发送请求,观察热点 Key 自动拆分到多个分片
rank:top100
product:flash
coupon:pool
user:hot:001
拆分后的分片 Keys:
请求次数
0
3 集群与高可用 — 三重保障

🌐 Redis Cluster

  • 16384 个 slot 分配给多个主节点
  • 水平扩展,存储和写入线性增长
  • 节点间 Gossip 协议互相探活

👮 Sentinel 哨兵

  • 持续监控主从节点状态
  • 主节点故障时自动选举新主
  • 客户端通过哨兵获取最新主节点地址

🏢 多机房部署

  • 跨机房主从同步,避免单机房故障
  • 同机房读,异机房做灾备
  • 网络分区时优先保证可用性
4 性能优化 — Pipeline / 大 Key / 持久化

⚡ Pipeline 对比:批量发命令 vs 逐条发

Pipeline 把多条命令打包一次性发给 Redis,减少 RTT(Round-Trip Time),吞吐提升 5~10x。
❌ 逐条发送(无 Pipeline)
✅ Pipeline 批量发送

🚫 避免大 Key

大 Key(如 Hash 里有百万字段)会导致:

  • 单次操作耗时长,阻塞其他命令
  • 序列化/反序列化慢,内存不连续
  • 迁移、持久化时产生巨大 IO 压力
方案:HGETALL → HSCAN 分批读;大 Hash 拆成多个小 Hash

💾 持久化调优

  • AOF everysec:每秒 fsync,最多丢 1s 数据,性能影响小
  • 关闭 RDB(或低频触发):大促期间 RDB fork 子进程会产生 Copy-on-Write 压力
  • 内存充足时开 no-appendfsync-on-rewrite yes,AOF 重写时不阻塞主线程
5 熔断与降级 — Redis 挂了怎么办?

⚡ 熔断(Circuit Breaker)

Redis 异常率超过阈值时,立即断开对 Redis 的请求,直接返回兜底数据或报错,避免大量请求堆积引发雪崩。

常用框架:Sentinel(阿里)、Hystrix(Netflix)、Resilience4j

🪂 降级(Fallback)

Redis 不可用时,按优先级降级:

  • 1️⃣ 本地缓存(Guava Cache / Caffeine)
  • 2️⃣ 返回默认值或空数据
  • 3️⃣ 降级到数据库(加限流保护)
  • 4️⃣ 降级到静态页面 / CDN

🔌 熔断器状态机演示

点击状态切换,了解熔断器三态转换

✅
CLOSED(正常)
请求正常通过 Redis
→
🚨
OPEN(熔断)
直接拒绝,走降级逻辑
→
🔶
HALF-OPEN(探测)
放少量请求试探 Redis
当前:CLOSED 状态 — Redis 正常服务,所有请求通过
6 监控与日志 — 大促期间的眼睛
慢查询日志:开启 slowlog-log-slower-than 10000(单位微秒),记录超过 10ms 的命令。 重点排查 HGETALL、SMEMBERS、SORT 等全量操作,用 HSCAN/SSCAN 替代。

📊 必监控指标

  • QPS(命令/秒)— 告警阈值:> 80% 峰值容量
  • 内存使用率 — 告警阈值:> 80%
  • 命中率(hit_rate)— 告警阈值:< 90%
  • 连接数 — 告警阈值:> maxclients × 80%
  • 主从复制延迟(replication_lag)
  • 慢查询数量(slowlog_len 变化速率)

🚨 告警分级

  • P2 警告:内存 > 70%,QPS > 70% 峰值容量
  • P1 严重:主从延迟 > 10s,命中率 < 85%
  • P0 紧急:主节点不可用,内存 OOM,熔断触发

工具栈:Prometheus + Grafana + Redis Exporter + PagerDuty

测 测一测,你学会了吗?
Q1. 大促前缓存预热的核心目的是什么?
A减少 Redis 内存占用
B提前加载热点数据,避免大量请求穿透到数据库造成雪崩
C给 Redis 集群做数据均衡
Q2. 热点 Key 拆分后,写操作应该怎么处理?
A随机写一个分片,其他分片靠过期自动失效
B广播更新所有分片,保证一致性
C只写原始 Key,分片只读不写
Q3. 大促期间为什么建议关闭 RDB 或降低 RDB 频率?
ARDB 会清空内存中的数据
BRDB 不支持大促场景
CRDB fork 子进程产生 Copy-on-Write,大促高写入时 COW 内存翻倍,影响主进程性能
Q4. 熔断器从 OPEN 状态变为 CLOSED 状态,需要经过哪个中间状态?
APAUSED(暂停)
BHALF-OPEN(半开)
CSTANDBY(待机)
面试一句话总结:大促 Redis 架构 = 预防(缓存预热 + 本地缓存)+ 容错(Cluster + Sentinel + 熔断降级)+ 优化(Pipeline + 拆 Key + 持久化调优)+ 可观测(QPS/内存/命中率监控)
🔥

预防

缓存预热 + 本地缓存 + 互斥锁,防止缓存穿透/击穿/雪崩

🛡️

容错

Redis Cluster + Sentinel + 多机房 + 熔断降级,保证高可用

⚡

优化

Pipeline + 避免大 Key + AOF everysec,压榨每一毫秒性能