以下是针对Redis集群恢复后重新分配槽位的标准化操作指南,结合生产环境最佳实践整理,包含不同场景下的详细步骤和注意事项:
一、槽位分配核心原理
Redis集群通过**哈希槽(Hash Slot)**实现数据分片,共16384个槽位,分配规则如下:
-
槽位分布机制
- 每个主节点负责连续的槽位范围(如节点A负责0-5460,节点B负责5461-10922)
- 槽位分配采用区间形式,例如节点A的槽位范围可能显示为
0-500,1000-2000
(非连续分配时) - 从节点不直接存储槽位数据,仅作为主节点的热备副本
-
客户端路由逻辑
- 客户端通过CRC16(key) % 16384计算键的槽位值
- 当访问的键不属于当前节点时,会返回MOVED重定向响应
- 智能客户端(如Lettuce)会缓存slot-node映射关系
二、恢复后重新分配槽位的场景
场景1:部分节点恢复(需重新分配)
典型故障现象:
redis-cli cluster nodes
显示部分节点状态为fail
或handshake
- 槽位状态出现
importing
/migrating
标志 - 集群状态为
cluster_state:fail
(通过CLUSTER INFO
查看)
恢复操作流程:
- 先通过
CLUSTER FAILOVER
命令恢复故障节点 - 检查各节点数据一致性:
redis-cli --cluster check <host>:<port>
- 对数据不一致的槽位执行强制修复:
redis-cli --cluster fix <host>:<port>
场景2:集群扩容后(需调整分配)
负载均衡策略:
- 新增节点后建议采用渐进式迁移(每次迁移约5%的槽位)
- 计算公式:
每个节点槽位数 ≈ 16384 / 主节点数量 ± 允许偏差值
- 监控指标:各节点内存使用率差异应<15%,QPS差异<20%
三、重新分配槽位的操作步骤
方法1:使用redis-cli --cluster reshard命令(推荐)
完整交互示例:
$ redis-cli --cluster reshard 192.168.1.101:7001
>>> Performing Cluster Check (using node 192.168.1.101:7001)
M: 1f2b3c4d... 192.168.1.101:7001 slots:[0-5460] (5461 slots) master
M: 5e6f7g8h... 192.168.1.102:7001 slots:[5461-10922] (5462 slots) master
[OK] All nodes agree about slots configuration.
How many slots do you want to move (from 1 to 16384)? 1000
What is the receiving node ID? 1f2b3c4d... # 目标节点ID
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes.
Type 'done' once you entered all the source nodes.
Source node #1: 5e6f7g8h... # 源节点ID
Source node #2: done
Do you want to proceed with the proposed reshard plan (yes/no)? yes
关键参数说明:
--cluster-slots
:指定单次迁移槽位数量(建议≤500)--cluster-timeout
:设置迁移超时时间(默认60秒)--cluster-pipeline
:批量迁移键数量(默认10)
方法2:手动迁移槽位(精细控制)
分步操作示例:
-
准备阶段:
# 在目标节点设置导入状态 redis-cli -h 192.168.1.101 -p 7001 CLUSTER SETSLOT 5461 IMPORTING 5e6f7g8h... # 在源节点设置迁移状态 redis-cli -h 192.168.1.102 -p 7001 CLUSTER SETSLOT 5461 MIGRATING 1f2b3c4d...
-
数据迁移阶段:
# 批量迁移该槽位的键(每次100个) redis-cli -h 192.168.1.102 -p 7001 CLUSTER GETKEYSINSLOT 5461 100 | \ xargs -L 100 redis-cli -h 192.168.1.102 -p 7001 MIGRATE 192.168.1.101 7001 "" 0 5000 KEYS
-
完成阶段:
# 通知所有节点更新槽位映射 redis-cli -h 192.168.1.101 -p 7001 CLUSTER SETSLOT 5461 NODE 1f2b3c4d...
四、自动化槽位分配脚本增强版
#!/bin/bash
REDIS_NODES="192.168.1.101:7001 192.168.1.102:7001 192.168.1.103:7001"
TARGET_MEMORY_USAGE=70 # 目标内存使用率阈值
# 动态计算需要迁移的槽位数
calculate_slots() {
local node=$1
local used_mem=$(redis-cli -h ${node%:*} -p ${node#*:} INFO MEMORY | grep used_memory: | awk -F: '{print $2}')
local max_mem=$(redis-cli -h ${node%:*} -p ${node#*:} CONFIG GET maxmemory | tail -1)
local usage=$((used_mem*100/max_mem))
if [ $usage -gt $TARGET_MEMORY_USAGE ]; then
echo $(( (usage - TARGET_MEMORY_USAGE) * 100 ))
else
echo 0
fi
}
for node in $REDIS_NODES; do
slots_to_move=$(calculate_slots $node)
if [ $slots_to_move -gt 0 ]; then
redis-cli --cluster reshard $node \
--cluster-from $(redis-cli -c -h ${node%:*} -p ${node#*:} CLUSTER NODES | grep master | awk '{print $1}') \
--cluster-to $(redis-cli -c -h ${node%:*} -p ${node#*:} CLUSTER NODES | grep master | grep -v ${node%:*} | head -1 | awk '{print $1}') \
--cluster-slots $slots_to_move \
--cluster-yes
fi
done
五、生产环境关键注意事项
-
迁移性能优化:
- 调整
repl-timeout
(默认60秒)避免超时中断 - 增加
cluster-node-timeout
(默认15秒)应对网络延迟 - 禁用THP:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
- 调整
-
监控指标清单:
watch -n 1 "redis-cli -h 192.168.1.101 -p 7001 CLUSTER INFO | grep -E 'cluster_slots_assigned|cluster_state'"
-
异常处理方案:
- 槽位冲突:执行
CLUSTER FLUSHSLOTS
重置状态 - 迁移卡死:重启对应节点触发拓扑重建
- 数据校验:使用
redis-check-rdb
工具验证备份文件
- 槽位冲突:执行
六、版本兼容性矩阵
操作命令 | Redis 5.x | Redis 6.x | Redis 7.x |
---|---|---|---|
CLUSTER ADDSLOTS | 支持 | 支持 | 支持 |
--cluster reshard | 部分支持 | 完全支持 | 完全支持 |
MIGRATE AUTH | 不支持 | 支持 | 支持 |
建议在操作前通过redis-server -v
确认集群版本一致性。