
文章目录数据量倾斜Bigkey 导致的倾斜Hash Tag 滥用槽分配不均数据访问倾斜热 key 的来源定位热 key应对方式本地缓存应对方式热 key 副本应对方式客户端缓存Redis 6.0数据倾斜的预防实践建议切片集群把数据均匀打散到多个节点理论上能让每个节点的负载差不多。但生产环境经常出现这样的情况明明用了集群某个节点还是被打爆了其他节点却很闲。这就是数据倾斜——数据或访问没有均匀分布。倾斜分两种数据量倾斜和数据访问倾斜原因和应对方式都不一样。数据量倾斜数据量倾斜指某个或某几个节点存的数据明显多于其他节点。原因主要有三个。Bigkey 导致的倾斜某个 key 本身的 value 极大——一个 List 几百万元素、一个 Hash 几百万 field、一个 Set 几亿成员。这种 key 不管路由到哪个节点都会把那个节点占满。定位 bigkeyredis-cli--bigkeys# 扫描所有 key输出每种类型最大的几个或者用MEMORY USAGE命令查看具体 key 的内存占用MEMORY USAGE user:profile:big_one应对方式拆分 bigkey。原 key: user:followers:1001 Set(1000万成员) 拆分后: user:followers:1001:0 Set(100万) user:followers:1001:1 Set(100万) ... 拆成 10 份读取时按规则去多个 key 聚合。代价是逻辑变复杂、跨节点查询多了但解决了数据倾斜的根本问题。Hash Tag 滥用Redis Cluster 支持 Hash Tag——key 中{}内的部分用于计算槽位user:{1001}:profile → CRC16(1001) → 槽 X user:{1001}:orders → CRC16(1001) → 槽 X这能把同一用户的多个 key 聚到同一节点方便做跨 key 操作。但如果大量 key 用了相同的 Hash Tag所有这些 key 都会落到同一个槽、同一个节点。最常见的错误是用业务前缀做 Hash Tagorder:{shop_1}:1001 order:{shop_1}:1002 order:{shop_1}:1003 ... 该店铺所有订单全到一个节点如果店铺 1 是大客户几百万订单全压在一个节点上。应对方式只在确实需要原子操作的 key 上用 Hash Tag不要随意加。槽分配不均集群初始化或扩容时如果手工分配槽可能没分均匀。比如 4 个节点节点A:0-80008000个槽 节点B:8001-120004000个槽 节点C:12001-140002000个槽 节点D:14001-163832000个槽A 节点承载的槽数是 D 的 4 倍数据量自然倾斜。应对方式用redis-cli --cluster rebalance或cluster reshard重新均匀分配。数据访问倾斜数据量分布均匀访问量却不均匀。某个 key 被频繁访问导致它所在的节点 CPU、网络打满而其他节点很闲。这就是热 key 问题。热 key 的来源明星动态某条微博突然爆火。热销商品双 11 的爆款。热点事件突发新闻、明星八卦。抢购页面限时优惠。热 key 往往是业务侧无法预测的。定位热 key# Redis 4.0 支持redis-cli--hotkeys# 需要 maxmemory-policy 设为 allkeys-lfu 或 allkeys-lru也可以通过MONITOR抽样观察请求分布但 MONITOR 性能开销大慎用。应对方式本地缓存热 key 的访问大部分是只读的。在应用层加本地缓存如 Caffeine、Guava Cache让大部分请求在应用本地就返回不走 RedisLoadingCacheString,StringlocalCacheCaffeine.newBuilder().maximumSize(1000).expireAfterWrite(5,TimeUnit.SECONDS).build(key-redis.get(key));短 TTL几秒能保证一致性长 TTL 能更好挡流量。具体值看业务容忍。应对方式热 key 副本把热 key 复制到多个 key分散到多个节点原 key:hot_news_1001 副本 hot_news_1001:0,hot_news_1001:1,...,hot_news_1001:N读取时随机选一个副本copy_idrandom.randint(0,N)keyfhot_news_1001:{copy_id}写入时所有副本都更新牺牲一致性换取读性能。这个方案适合读多写少的热 key。如果是写多读少的比如计数器副本方案就不行了。应对方式客户端缓存Redis 6.0Redis 6.0 引入了 Tracking 机制服务端在 key 变更时主动通知客户端失效。客户端可以放心做本地缓存不用担心读到旧数据。CLIENT TRACKING ON GET hot_news_1001# 服务端会记住这个客户端读过这个 key# key 变更时主动通知失效这是优雅的方案但需要客户端库支持。数据倾斜的预防事后处理不如事前预防。架构设计阶段就要考虑避免单一维度的 key 设计不要让所有 key 都按一个 ID 分布。慎用 Hash Tag只在跨 key 原子操作时用不要为了看起来整齐加。预估数据规模业务上线前估算每个 key 的数据量超过阈值的提前拆。监控告警每个节点的内存、QPS、CPU 都要监控倾斜要及时发现。实践建议定期扫 bigkey--bigkeys命令成本不高可以每周运行一次。bigkey 拆分要趁早等到把节点压垮再拆要做的工作多得多。Hash Tag 只用在必要的地方默认不要加要加之前问清楚为什么。热 key 做本地缓存成本最低收益最大的方案。关键业务做读副本电商首页的爆款商品、社交平台的热门内容。集群扩容时重新均衡扩容只是加节点不会自动迁移数据必须手动 rebalance。数据倾斜是切片集群必然会遇到的问题。理解倾斜的两种来源——数据量和访问量——才能对症下药。bigkey 拆分、Hash Tag 谨慎使用、热 key 副本和本地缓存构成了应对数据倾斜的工具箱。把这些手段用对集群才能真正发挥水平扩展的价值。