RESHARD迁移卡顿源于MOVE命令同步搬运大Key时阻塞slot读写,导致延迟、超时与CPU飙升;需手动分批迁移、验证并拆分大Key、显式设置MIGRATE timeout。

RESHARD迁移卡顿是因为MOVE命令阻塞slot读写
Redis集群reshard过程中出现明显延迟、客户端超时、CPU飙升,根本不是网络或磁盘慢,而是MOVE命令在搬运大Key时必须原子性完成整个value的序列化→传输→反序列化。一个500MB的zset会锁死源节点和目标节点上该slot的所有读写操作,其他小key也得排队等——这和IO负载无关,是单线程同步搬运模型决定的。
常见错误现象包括:CLUSTER SLOTS返回状态长期卡在MIGRATING或IMPORTING、redis-cli --cluster check卡住、客户端频繁收到MOVED重定向但请求无响应。
- 不要指望调大
cluster-node-timeout来“扛过去”——它只影响故障检测,不缓解迁移阻塞 - 自动reshard(
redis-cli --cluster reshard)默认批量迁移1000个slot,但实际是按key逐个MOVE,无法控制单次搬运节奏 - 迁移前未识别大Key,导致中途被某个50MB的
hash卡住12分钟,运维误判为网络中断而重试,反而加剧积压
用CLUSTER SETSLOT手动分批迁移slot
跳过自动reshard流程,改用人工控制slot迁移节奏,核心是把“一次搬完”拆成“一批一批搬”,每批只包含少量key(最好
操作前必须停写对应slot的业务流量(例如通过配置中心关闭写入口),否则MOVE期间新写入会被转发到目标节点,造成数据重复或丢失。
- 先查出要迁的slot范围:
redis-cli -c -p 7001 cluster slots | grep "7001" - 对每个待迁slot,执行两步状态设置:
CLUSTER SETSLOT <slot_id> MIGRATING <target_node_id></target_node_id></slot_id>(源节点),再在目标节点执行CLUSTER SETSLOT <slot_id> IMPORTING <source_node_id></source_node_id></slot_id> - 用
SCAN配合MIGRATE逐key迁移:redis-cli -c -p 7001 scan 0 match "*{slot_hash}" count 10 | xargs -I {} redis-cli -p 7001 migrate 192.168.1.101 7004 "" 0 5000 replace(注意timeout设为5000ms,避免无限等待) - 每批迁移后,用
redis-cli -p 7001 cluster countkeysinslot <slot_id></slot_id>确认key数归零,再CLUSTER SETSLOT <slot_id> NODE <target_node_id></target_node_id></slot_id>提交slot归属
迁移前必须用redis-cli --bigkeys筛出大Key
KEYS *绝对不能用——它会阻塞主线程,且无法反映真实内存占用;MEMORY USAGE单key查又太慢。真正高效的方式是让Redis自己扫描并统计:
redis-cli -p 7001 --bigkeys会输出各类型最大key及其元素数/长度,同时记录扫描耗时与总key数,比人工HLEN/ZCARD更准更快。
- 阈值建议:string > 10KB、hash/zset/list > 1k元素、set > 500成员,就标记为待拆分
- 输出里带
[0]的行是疑似大Key,但需二次验证:redis-cli -p 7001 memory usage "key_name" - 发现大Key后,不要直接
DEL,先用HSCAN/ZSCAN分批导出,再重建为多个小key(如user:1001:profile:0,user:1001:profile:1),最后切流量+清理旧key
MIGRATE命令timeout参数必须显式设置
MIGRATE默认同步等待响应,不设timeout时可能无限挂起,导致源节点连接池耗尽、后续请求全部堆积。尤其在跨机房或高延迟链路下,这个坑踩中就是雪崩起点。
正确写法必须带timeout毫秒值,并配合replace防止目标已存在同名key干扰:
redis-cli -p 7001 migrate 192.168.1.101 7004 "mykey" 0 3000 replace
- timeout建议设为3000–5000ms:太短容易误判失败,太长会拖垮源节点
- 不要用
copy选项——它会让源key保留,违反迁移语义,且增加内存压力 - 批量迁移时,避免用shell管道拼接大量
MIGRATE命令,应改用Lua脚本或客户端批量发送,减少网络往返
真正难的不是命令怎么写,而是判断哪些slot能一起迁、哪些key必须单独拎出来处理。每次迁移前花10分钟跑一遍--bigkeys,比事后花2小时排查卡点划算得多。


















