10.性能优化
文章目录
问题: 什么是大 Key 和热 Key?它们分别会带来哪些性能风险?请说明如何发现、处理大 Key(如拆分、异步清理),以及如何应对热 Key(如多副本、本地缓存)。
👇 点击展开/折叠 面试背诵模板(建议先背这个)
一、定义与判定标准
| 问题 | 定义 | 典型阈值 |
|---|---|---|
| 大 Key | 单个 key 存储的数据量过大,或集合中元素数量过多 | String > 10KB;List/Hash/Set/ZSet 元素数 > 1万 或 总大小 > 1MB |
| 热 Key | 在短时间内被大量并发请求访问的 key | QPS > 1万 或 占整体请求比例 > 1% |
二、性能风险分析
大 Key 带来的风险:
- 读取/写入慢:
GET、HGETALL、SMEMBERS等命令执行耗时高(O(N)),阻塞主线程,影响其他请求响应。 - 删除阻塞:
DEL大 Key 是同步阻塞操作,回收内存可能耗时数百毫秒甚至秒级,导致 Redis 卡顿。 - 网络带宽压力:单次返回数据量大,出口带宽被打满。
- 集群数据倾斜:集群模式下,大 Key 所在节点内存和 CPU 利用率远高于其他节点,影响扩容效率。
热 Key 带来的风险:
- 单节点 CPU 飙高:所有读请求集中在一个分片,CPU 成为瓶颈,其他分片闲置。
- 缓存击穿链式反应:热 Key 失效瞬间,大量并发请求直达数据库,可能压垮 DB。
- 网络中断风险:极端热点可能导致网卡打满或连接数耗尽。
三、发现与监控方法
大 Key 发现:
redis-cli --bigkeys:扫描全库,统计各数据类型最大 key(线上慎用,可能影响性能)。MEMORY USAGE key:精确计算单个 key 的内存占用(O(1) 返回)。- RDB 分析工具:通过
redis-rdb-tools离线分析 RDB 文件,无侵入。 - 监控指标:节点内存使用率、慢查询日志(
slowlog)中包含大 Key 操作。
热 Key 发现:
- Redis 4.0+ 的 LFU 统计:
OBJECT FREQ key返回访问频率(对数计数)。 redis-cli --hotkeys:基于 LFU 统计扫描热 Key(需设置maxmemory-policy为 LFU 策略)。- 业务侧监控:在客户端(如 Jedis、Lettuce)埋点统计访问频次。
- 代理层统计:Twemproxy/Codis 层可记录每个 key 的 QPS。
四、处理与优化策略
大 Key 处理方案:
① 拆分(分片存储):将一个大 Hash 拆为多个小 Hash,按字段 ID 取模分片;或把大 List 按时间分段,拆成多个小 List。
② 压缩存储:在写入前对 value 进行压缩(如 GZIP),读取后解压,以 CPU 换内存和带宽。
③ 异步删除:使用 UNLINK 替代 DEL,后台线程异步回收内存,不阻塞主线程。
④ 定期清理:对过期大 Key 设置合理的 TTL,避免无限累积;对无用的大 Key 定时分批删除(SCAN + UNLINK)。
热 Key 应对方案:
① 多副本(读写分离):为热 Key 所在的 Redis 节点增加只读从节点,将读请求分散到多个副本,降低主节点压力。
② 本地缓存(JVM Cache):在应用层引入本地缓存(如 Caffeine、Guava Cache),设置短 TTL(如 5 秒),拦截热 Key 请求,大幅减少 Redis 访问量。
③ 热点缓存(Hotspot Cache):在 Redis 前加一层代理(如 Twitter 的 Twemproxy)或 CDN,将热点数据提前分发到边缘节点。
④ 随机过期 + 互斥锁:对热 Key 设置随机过期时间(避免集中失效),失效时使用互斥锁(SETNX)保证单线程重建缓存,其他线程等待或返回旧值。
五、治理原则总结
- 防御优先:大 Key 在写入时主动拆分,而非依赖事后清理。
- 多级缓存:对热 Key 构建“本地缓存 → Redis → DB”三级体系,逐级削减峰值流量。
- 可观测性:建立大 Key 和热 Key 的监控大盘,设置告警阈值(如节点内存 > 80%、单 Key QPS > 5000),做到早发现早处理。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 LGQ的博客!