先看INFO CPU中used_cpu_sys和used_cpu_user是否同步飙升:若仅sys飙升,是连接层压力;若两者齐涨且migrating_slots/importing_slots非零,才是数据迁移导致。
直接看INFO CPU 里的 used_cpu_sys 和 used_cpu_user 是否同步飙升——如果不是,就别急着归因到数据迁移。Redis集群扩容时CPU飙高,90%以上不是迁移本身的问题,而是客户端行为失控引发的连锁反应。
used_cpu_sys 显著升高(比如翻倍),used_cpu_user 变化不大,基本是连接层压力:大量短连接重建、TLS握手、或客户端频繁重连used_cpu_sys 和 used_cpu_user 同步上涨,再查 INFO cluster 中 migrating_slots 和 importing_slots 是否非零;非零才说明真有迁移在跑redis-cli -c -h node1 -p 6379 cluster nodes | grep -E "(migrating|importing)" 确认哪些节点正在参与迁移tcpdump -i lo port 6379 -w redis-cpu.pcap,过滤出是否集中发往正在迁移的源节点(而非随机打满所有节点)这个命令默认对每个槽执行 CLUSTER GETKEYSINSLOT + 多轮 SCAN,和 MIGRATE 争抢单线程资源,尤其在目标节点负载已高时,会卡住迁移队列并抬高 used_cpu_sys。
--cluster check,改用轻量轮询:redis-cli -h src -p 6379 cluster countkeysinslot {slot} 2>/dev/null 对比 redis-cli -h dst -p 6379 dbsize
--cluster check 时,加 --verbose --slots 100 限制抽样槽数(注意:仅 Redis 6.2+ 支持 --slots 参数)MOVED 响应本身不耗时(纯文本),真正卡点在于客户端处理逻辑。而 TRYAGAIN 错误才是迁移中键被锁定的真实信号——此时源节点拒绝写入,客户端若没 sleep 就重试,会形成自旋风暴。
TRYAGAIN 并主动 sleep(50–100ms) 后重试,不能当成普通失败立刻重发KEYS *、FLUSHDB、SCAN 全量操作,它们会触发 slot 锁等待,放大阻塞redis-cli --cluster rebalance --threshold 1 可降低单次迁移槽数量,减小锁粒度(但要注意:该参数在 Redis 6.2+ 才生效)TRYAGAIN 的静默忽略——它不像 MOVED 那样触发路由更新,也不像网络错误那样明显报错,但会让请求在源节点反复排队、超时、重试,最终表现为“延迟突增+CPU错峰上涨”。