必须先验证槽位分布再操作,用redis-cli cluster countkeysinslot遍历0–16383统计各slot key数,超均值5倍的需查hash tag;reshard时注意输入格式、node ID精确性及客户端映射刷新。

槽位倾斜必须先确认再动手,盲目 reshuffle 可能加剧请求错发或节点过载。
怎么快速定位哪个 slot 或节点明显偏高
不能只看 cluster info 里各节点的 keys 数,因为 key 数不等于 slot 负载——一个 bigkey 占用大量内存但只占 1 个 slot,而 1000 个小 key 分散在 10 个 slot 可能更均衡。真问题在 slot 分布本身。
分两步验证:
- 用
redis-cli -c -h {host} -p {port} cluster countkeysinslot {slot}扫描所有 slot(需遍历 0–16383),统计每个 slot 的 key 数量;平均值 = 总 key 数 ÷ 16384,超过平均值 5 倍的 slot 就要重点查 - 对高 key 数 slot,执行
cluster getkeysinslot {slot} 100拉出样本,观察是否集中出现相同{xxx}结构(比如全为order:{202409}:*)——这是 hash tag 导致的典型倾斜
reshard 迁移时最容易卡住的三个输入点
redis-cli --cluster reshard 是交互式命令,每一步输错都会中断,且无回退:
- 第一问「How many slots do you want to move?」填 0 或 >16384 直接退出;填 600 表示迁移 600 个 slot,不是 key 数
- 第二问「What is the receiving node ID?」必须复制
cluster nodes输出中完整、大小写精确的 node ID(如2728a594a0498e98e4b83a537e19f9a0a3790f38),少一位或粘贴带空格就报No such node - 第三问「Please enter all the source node IDs」填
all表示从所有主节点等比例抽槽;填单个 ID 时若该节点已无可用 slot,命令会卡在Source node 1:不动
客户端还在打旧节点?不是命令失败,是映射没刷新
reshard 完成后,MOVED 响应已生效,但客户端未必立刻路由正确:
- 老连接不会自动 reload slot 映射,Lettuce 需显式调用
client.reloadPartitions(),JedisCluster 默认不自动刷新,得重启连接池或等连接自然超时轮换 -
redis-cli -c每次命令都是新连接,能立即走新路由;但业务代码复用连接时,可能持续错发 1–2 分钟 - 检查客户端日志是否频繁出现
ASK(迁移中临时重定向)而非MOVED(永久切换),只有MOVED才触发客户端更新本地 slot-node 表
改完 key 规则后必须验证的两个动作
改了 hash tag 或 key 格式后,别直接上线:
- 用线上流量镜像或构造测试数据,跑一遍新 key 生成逻辑,用 Python 快速验证 slot 分布:
python -c "import crcmod.predefined; c=crcmod.predefined.Crc('crc-16'); print(c(b'new_key') % 16384)",批量生成 1000 个 key 看 slot 是否分散 - 在预发集群部署后,不要只看
cluster info,要同时比对memory_used_human和keys,两者都收敛在 ±5% 内才算真正均衡
最容易被忽略的是客户端 SDK 缓存了旧的 slot 映射关系,尤其 JedisCluster 的 refreshNodeInfo 默认关闭,改 key 后不主动刷新,请求就会永远错发——这不是服务端问题,是客户端没同步。


















