26人参与 • 2026-02-28 • Redis
在高并发的分布式系统中,redis 作为高性能的内存数据库,广泛用于缓存、会话存储、计数器等场景。然而,随着业务规模的增长,热 key(hot key)问题逐渐成为影响系统稳定性和性能的重要隐患。
热 key 是指在 redis 中被高频访问的某个 key,其访问频率远超其他 key,导致该 key 所在的 redis 实例或节点成为系统瓶颈。
| 问题 | 影响 |
|---|---|
| 单点瓶颈 | 热 key 集中在一个 redis 节点,导致该节点负载过高,影响其他 key 的访问。 |
| 网络带宽耗尽 | 高频读写导致网络 io 达到瓶颈,响应变慢。 |
| cpu 过载 | redis 单线程处理命令,热 key 导致主线程阻塞,影响其他请求。 |
| 缓存雪崩风险 | 若热 key 失效,大量请求直接打到数据库,可能压垮 db。 |
| 主从延迟 | 写热 key 时,主节点压力大,同步到从节点延迟增加。 |
这是最简单直接的方式,适用于 redis 4.0+ 版本。
redis 内置了基于 lfu(least frequently used)算法 的热点 key 发现机制。通过采样命令访问频率,自动识别出访问最频繁的 key。
# 连接 redis 并启动热 key 检测 redis-cli --hotkeys # 可指定 host 和 port redis-cli -h 127.0.0.1 -p 6379 --hotkeys
# scanning the entire keyspace to find hot keys as well as
# average sizes per pattern of keys.
# 1 hottest key found at 'user:profile:10086' with 12532 hits
# 2 hottest key found at 'product:detail:hot' with 9823 hits
maxmemory-policy 为 lfu 相关策略(如 allkeys-lfu 或 volatile-lfu),否则可能无效。虽然不直接找“热 key”,但可以间接发现性能瓶颈。
# 查看最近 10 条慢查询 slowlog get 10 # 查看慢查询总数 slowlog len # 重置慢日志 slowlog reset
id: 日志 idtimestamp: 执行时间戳duration: 执行耗时(微秒)cmd: 完整命令(包含 key 名)如果某个 key 多次出现在慢日志中,很可能是热 key 或大 key。
在 redis.conf 中设置:
slowlog-log-slower-than 10000 # 超过 10ms 的命令记录 slowlog-max-len 1024 # 最多保存 1024 条日志
思路:在应用层使用本地缓存(如 caffeine、guava cache)缓存热 key,减少对 redis 的直接访问。
// 示例:使用 caffeine 缓存热 key
loadingcache<string, string> cache = caffeine.newbuilder()
.maximumsize(1000)
.expireafterwrite(5, timeunit.minutes)
.build(key -> redis.get(key));
string value = cache.get("hot:product:123");优点:简单高效,显著降低 redis 压力。
缺点:存在缓存不一致问题,需设置合理过期时间。
思路:将一个热 key 拆分为多个子 key,分散访问压力。
# 原始热 key set hot:product:123 "details" # 拆分为多个 key set hot:product:123:1 "details_part1" set hot:product:123:2 "details_part2"
读取时:随机选择一个子 key 读取,或合并多个。
适用场景:读多写少,且数据可拆分。
思路:将读请求打到 redis 从库,写请求打到主库。
注意:从库有延迟,对一致性要求高的场景慎用。
思路:通过 redis cluster 将 key 分布到多个节点,避免单点过热。
建议:为特别热的 key 单独部署一个 redis 实例。
思路:避免大量请求同时触发缓存重建。
// 使用 scheduledexecutorservice 定时刷新 scheduler.scheduleatfixedrate(this::refreshhotkey, 0, 4, timeunit.minutes);
思路:在应用层对热 key 访问进行限流,防止系统崩溃。
@sentinelresource(value = "gethotkey", blockhandler = "handlehotkey")
public string gethotkey() {
return redis.get("hot:key");
}
public string handlehotkey(blockexception ex) {
return "default_value";到此这篇关于redis 热 key 问题的解决的文章就介绍到这了,更多相关redis 热 key 内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论