单节点性能瓶颈源于请求集中打到同一slot和物理节点,需从访问路径分流;本地缓存通过进程内存储绕过Redis单线程与网络IO,实现QPS横向分摊,但须设短过期时间、限制容量、同步更新;多副本负载均衡依赖客户端随机路由副本key,而非服务端转发;redis-cli--hotkeys需LFU策略才有效,副本key必须带TTL并由写操作主动刷新。

单节点性能瓶颈的根源不在 Redis 本身,而在请求集中打到同一个 key 对应的 slot 和物理节点上。直接扩容或调参治标不治本,必须从访问路径上做分流。
为什么本地缓存能缓解热点 Key 压力
本地缓存(如 Caffeine、Guava)把高频读取的 value 直接存在应用进程内存里,绕过网络 IO 和 Redis 单线程处理环节。对 product:1001:info 这类读多写少的数据,命中本地缓存后,QPS 压力从 Redis 节点转移到应用 CPU,天然实现横向分摊。
但要注意几个硬约束:
- 必须设短过期时间(如
expireAfterWrite(2, TimeUnit.SECONDS)),否则数据陈旧风险高 - 不能用于强一致性场景(如库存扣减),只适合容忍秒级延迟的展示类数据
- 缓存容量要限制(如
maximumSize(5000)),避免 OOM - 更新需同步:Redis 写入后,应通过 Pub/Sub 或消息队列通知所有应用节点清理对应本地缓存
多副本负载均衡的关键是「客户端路由」而非服务端转发
Redis 集群本身不解决热 Key 倾斜——hot_key 经哈希计算仍落在固定 slot,所有请求还是打到同一节点。真正有效的做法是在客户端做随机副本选择:
- 预设多个副本 key:
hot_key:replica1、hot_key:replica2、hot_key:replica3 - 写操作时,用
pipeline同时更新全部副本 - 读操作时,用
ThreadLocalRandom.current().nextInt(3)随机选一个副本读,失败再 fallback 到主 key 或 DB - 副本间一致性靠写时广播保障,不依赖 Redis 自身复制延迟
这种方式把单点压力均摊到 N 个 Redis 实例,但要求客户端 SDK 封装好路由逻辑,不能依赖 proxy 层(如 Twemproxy 不支持动态副本路由)。
容易被忽略的两个细节
一是 redis-cli --hotkeys 只在启用 LFU 淘汰策略(maxmemory-policy allkeys-lfu 或 volatile-lfu)时才有效,未配置会返回空结果;二是本地缓存 + 多副本组合下,如果副本 key 的 TTL 设置为永不过期,而主 key 过期后未触发副本刷新,会导致长期脏读——必须让所有副本都带 TTL,且由写操作主动刷新。



















