bigywater.tech
Redis · 82

Redis Cluster 中的大 Key

单机上大 key 的问题是慢命令、内存;集群里它还多出三个问题:数据看起来均衡其实不均衡、迁移时会卡住整个节点、更糟的是节点被卡住太久会被整个集群判死。这篇用一个 200 MB 的 key 把三个问题都复现一遍。(每一步的数字来自本机;最后一步的「阻塞」是我用 DEBUG SLEEP 模拟的。)

222 vs 12.2 MB
槽位数、DBSIZE 都均衡时,含大 key 的主库与另外两个主库的内存
423 ms
迁移含 200 MB 大 key 的槽时,源节点上 PING 的最大停顿
4498 ms
主库被阻塞 5 秒(超过 node-timeout)后,从库升主所用的时间

均衡的假象

实测 · 本机执行输出
    主库     槽位数   DBSIZE   used_memory
  7540    5461   100017       12.2 MB
  7541    5462    99976      222.0 MB   ← 大 key 所在
  7542    5461   100008       12.2 MB

槽位数、key 数量是集群「均衡」的通常指标,三个主库都是 5461/5462/5461、约 10 万个 key。但 7541 上有一个 200 MB 的 key,内存 222 MB,另外两个只有 12.2 MB。这个 key 只占 1 个槽、1 个 key,在槽位数与 DBSIZE 上完全不可见。内存告警、RDB 大小之类的问题理论上也会先在这个分片上出现(这一点本文没有实测)。

rebalance 帮不上忙

实测 · 本机执行输出
  >>> Performing Cluster Check (using node 127.0.0.1:7540)
  >>> Check for open slots...
  >>> Check slots coverage...
  *** No rebalancing needed! All nodes are within the 2.00% threshold.

redis-cli --cluster rebalance 按槽位数(可以加权重)均衡,它给出的结论是 No rebalancing needed! All nodes are within the 2.00% threshold。要疏散大 key,我能想到的办法是人工找到含它的槽再迁走,或者拆分这个 key(有没有别的工具,本文没有验证)。

迁移含大 key 的槽:卡住整个源节点

实测 · 本机执行输出
  槽内 19 个 key(含大 key)MIGRATE → OK,耗时 424 ms;源节点 7541 上另一个连接的 PING 最大停顿 423 ms(平时约 0.03 ms)

手工迁移这个槽(第 80 篇的四步):槽里 19 个 key,其中含 200 MB 的大 key,MIGRATE 用了 424 ms,期间源节点上另一个连接的 PING 最大停顿 423 ms——几乎等于整个 MIGRATE。第 81 篇量过:MIGRATE 在源上同步执行,所以这个节点的其它所有槽在这段时间里都不响应。

阻塞超过 cluster-node-timeout:被判死

实测 · 本机执行输出
  主库 7541 被阻塞 5 秒:其它节点 PFAIL 3419 ms,FAIL 3790 ms,它的从库 7544 升主 4498 ms
  阻塞结束后各节点角色: {7544: 'master', 7541: 'slave', 7545: 'slave', 7543: 'slave', 7540: 'master', 7542: 'master'}

如果这样的停顿(或者一次超大 key 的 DEL)超过 cluster-node-timeout(这里 3000 ms),其它节点收不到它的心跳,会把它标成 PFAIL、再确认 FAIL,从库发起选举升主(第 75、76 篇)。我用 DEBUG SLEEP 5 模拟 5 秒的阻塞:其它节点 3419 ms 标 PFAIL、3790 ms 标 FAIL,从库 4498 ms 升主。阻塞结束后原主库醒来,自己变成了从库(第 77 篇)。这是「模拟」的阻塞,不是真的大 key 操作;要说的是:任何持续超过 node-timeout 的主线程阻塞,不管原因,都会触发故障转移。

分步演示:大 key 在集群里的三个坑

Redis Cluster 中的大 Key
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。3 主 3 从,enable-debug-command yes(只为 DEBUG SLEEP 模拟阻塞);大 key 是一个 200 MB 的字符串
    • 没有验证:真实的大 key 删除(DEL / UNLINK)对集群的影响、大 hash/list 的迁移(MIGRATE 会分块吗)、cluster-node-timeout 设得更大时的取舍、从库上大 key 对复制缓冲区的影响
    京ICP备2026067502号-1京公网安备11010502063487号