单机上大 key 的问题是慢命令、内存;集群里它还多出三个问题:数据看起来均衡其实不均衡、迁移时会卡住整个节点、更糟的是节点被卡住太久会被整个集群判死。这篇用一个 200 MB 的 key 把三个问题都复现一遍。(每一步的数字来自本机;最后一步的「阻塞」是我用 DEBUG SLEEP 模拟的。)
主库 槽位数 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 大小之类的问题理论上也会先在这个分片上出现(这一点本文没有实测)。
>>> 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(有没有别的工具,本文没有验证)。
槽内 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 在源上同步执行,所以这个节点的其它所有槽在这段时间里都不响应。
主库 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 的主线程阻塞,不管原因,都会触发故障转移。