Redis 热 Key 治理:发现热点只是第一步
一、热 Key 会把集群打成单点
Redis 集群看起来是分布式的,但一个热 Key 会把压力集中到单个分片。热门商品、配置项、活动库存、排行榜和登录态都可能成为热点。热 Key 的问题不只是延迟升高,还可能导致某个节点 CPU 飙高、网络打满,进而影响同分片其他 key。
治理热 Key 不能只靠扩容。扩容能增加整体容量,但单个 key 仍然落在一个分片上。真正的治理要从发现、拆分、缓存策略和降级一起做。
二、治理链路:监控发现到业务拆分
flowchart TD A[Redis 指标异常] --> B[热 Key 发现] B --> C[业务归因] C --> D[本地缓存] C --> E[Key 拆分] C --> F[请求合并] F --> G[降级保护]热 Key 发现可以用 Redis 自带命令、代理层统计、客户端埋点或云厂商工具。只知道某个 key 热还不够,要知道它来自哪个接口、哪个业务活动、读写比例和峰值时段。没有业务归因,就只能临时救火。
读热点和写热点治理不同。读热点可以考虑本地缓存、多级缓存、请求合并和副本读;写热点更麻烦,可能需要业务拆分、异步聚合或改变数据模型。把写热点当读热点处理,容易造成一致性问题。
三、代码示例:请求合并降低穿透
下面是一个简化思路:同一时刻同一个 key 只让一个请求回源。
public Product getProduct(String id) { String key = "product:" + id; Product cached = redis.get(key); if (cached != null) { return cached; } return singleFlight.doOnce(key, () -> { Product product = database.findProduct(id); redis.setex(key, 60, product); return product; }); }请求合并能减少缓存失效瞬间的回源压力,但不能解决长期热读。长期热 Key 可以加本地缓存,TTL 设短一点,接受秒级延迟。核心是让每次请求不都打到同一个 Redis 分片。
Key 拆分适合计数和排行榜等场景。比如把一个全局计数拆成多个 shard key,写入时随机分片,读取时聚合。代价是读取更复杂,数据不再天然强一致。业务必须接受这种取舍。
四、降级策略:热点活动要提前预案
热点通常不是完全随机的。大促、直播、秒杀、新功能发布都会制造热点。活动前要压测热点 key,准备本地缓存、限流、降级页面和只读模式。等节点 CPU 打满后再查,已经晚了。
监控要按分片看。集群平均 CPU 30% 没意义,单分片 95% 才是事故信号。网络、慢命令、key 访问频率和连接数都要拆分到节点维度。
最后,治理后要复盘 key 设计。为什么这个 key 会热?是否可以按租户、区域、业务维度拆?是否可以把实时查询改成异步刷新?热 Key 是症状,数据模型才是根。
热 Key 治理也要注意一致性。加本地缓存后,更新传播会变慢;Key 拆分后,读取聚合可能出现短暂不一致。不要只看 Redis 压力下降,还要看业务是否能接受这些延迟。架构优化的每一步,都要把收益和代价写清楚。
五、总结
Redis 热 Key 治理要从发现走到业务归因,再选择本地缓存、请求合并、Key 拆分、限流和降级。扩容只能缓解整体压力,不能消除单 key 热点。热点治理的最终答案,通常在业务模型里。