Redis 热 key 导致 QPS 飙到 20 万,如何通过本地缓存+拆分把压力降 80%
解读
- 场景定位:国内互联网大促、秒杀或热点事件,瞬时流量把单 key 打到 20 w QPS,Redis 单实例极限约 10 w QPS,已触发 CPU 打满、连接排队、RT 暴涨。
- 目标量化:降 80% 即剩余 4 w QPS 落到 Redis,16 w QPS 由本地缓存+拆分承担。
- 约束条件:
- 不能影响一致性——库存、金额类数据必须可接受秒级延迟或最终一致;
- 必须可灰度、可回滚——国内上线窗口短,凌晨封网;
- 必须兼容现有 SpringCloud/Dubbo 技术栈,中间件以阿里云、腾讯云主流产品为主。
知识点
- 热 key 识别:
- 阿里云 Redis 控制台“热 key 分析”、腾讯云 CRS 的 hotkey 命令、Redis 7.0本身 hotkeys 采样;
- 客户端埋点:基于 Lettuce/Redisson 的 Micrometer 指标,按 key 前缀聚合。
- 本地缓存选型:
- Caffeine:W-TinyLFU 算法,命中率高于 Guava,支持异步刷新;
- 多级缓存框架:JetCache、SpringCache 增强,支持 Redis→Caffeine 两级自动降级。
- 拆分策略:
- 水平拆分:把热 key 按 hash(tag)%N 拆成 N 个逻辑子 key,分散到不同 slot,避免单节点热点;
- 垂直拆分:将 value 中大字段剥离成独立 key,减少网络往返;
- 读写拆分:一主多从+LVS/Proxy,读请求路由到只读节点,国内云厂商支持读写分离地址。
- 一致性保障:
- 短过期+异步刷新:本地缓存设置 1–2 s TTL,后台定时线程 80% 时间点异步 reload,防止集中回源;
- 版本号/MD5 机制:Redis 存版本号,本地缓存对比版本,无变化直接返回;
- 增量广播:基于 Redis pub/sub 或 Canal+MQ 下发失效事件,各应用节点毫秒级删除。
- 压测验证:
- 使用阿里云 PTS/JMeter 脚本,线程组阶梯加压至 20 w QPS,监控 Redis qps、CPU、RT、本地缓存命中率;
- 命中率达到 80% 以上即满足降量目标;同时验证 GC、CPU L1 cache miss 无劣化。
答案
- 识别热 key
通过“阿里云 Redis 控制台–热 key 分析”发现 key 为 item_12345,QPS 20 w,value 2 KB,命中率 99.7%。
- 本地缓存兜底
- 应用层引入 Caffeine,配置 maximumSize=50 000、expireAfterWrite=1 s、refreshAfterWrite=800 ms;
- 使用 JetCache 的 @CacheRefresh 注解,异步线程池 core=4,防止集中回源;
- 增加 Redis 版本号:item_12345_ver,每次更新库存时自增;本地缓存刷新时先对比版本,无变化直接返回旧值,降低回源 QPS 60%。
- 水平拆分+读写分离
- 将 item_12345 拆成 item_12345_00~item_12345_31 共 32 份,使用 CRC16(tag)&31 算法,保证同一 tag 落在同一 slot;
- 32 份 key 均匀落在 8 主 8 从的集群,单 key 最高 QPS 降至 20 w/32≈6 250;
- 开启阿里云“读写分离”地址,读流量路由到只读节点,进一步把主节点压力再降 30%。
- 一致性策略
- 库存扣减走 MQ 异步消息,Redis 先减缓存再落 MySQL,本地缓存 1 s 过期,允许秒级延迟;
- 大促峰值过后,关闭本地缓存刷新,降级为直连 Redis,方便运营实时修正库存。
- 灰度与回滚
- 按用户尾号灰度 5%→20%→100%,实时监控错误率>1% 或 Redis QPS 异常反弹立即关闭本地缓存开关,秒级回滚;
- 压测报告:本地缓存命中率 82%,Redis QPS 降至 3.6 w,达成“降 80%”目标,P99 RT 从 68 ms 降到 5 ms。
拓展思考
- 若 value 为 100 KB 大 JSON,如何继续优化?
可再做垂直拆分:将商品基础字段与库存字段分离,基础字段本地缓存,库存字段走 Redis 拆分;同时使用 Redis compression(lz4)减少网卡流量。
- 本地缓存命中率无法提升的场景怎么办?
引入 SideCar 层 Redis Proxy(如 TendisPlus、Codis),在 Proxy 层做 LRU 二级缓存,应用无侵入;或把热 key 迁移到 Tair 的内存+SSD 混合存储,单节点可支撑 40 w QPS。
- 多活单元化架构下如何同步?
每个单元独立计算热 key,通过 Global Zone 广播版本号,单元内本地缓存各自兜底,跨单元数据冲突用业务层“预扣”+“对账”解决,符合国内金融级合规要求。