一、为什么需要动态删除节点?
在分布式系统中,Redis Cluster的节点增减是运维常态。某次我们遇到这样的情况:某台物理机即将过保需要下线,但上面运行着Redis集群的3个从节点。此时需要在不影响服务的前提下,将这些节点安全地从集群中移除。动态删除节点的核心价值在于:
- 硬件维护时实现服务平滑过渡
- 优化资源利用率(如缩容低负载节点)
- 集群版本升级前的节点清理
二、操作环境准备
技术栈说明:
本次演示基于:
- Redis 6.2.6 集群版
- Linux CentOS 7.6
- redis-cli 命令行工具
- 初始集群配置:3主3从共6节点
$ redis-cli -h 192.168.1.101 -p 6379 cluster nodes
# 输出示例:
f3c2... 192.168.1.101:6379@16379 master - 0 1625000000000 3 connected 10923-16383
a1b2... 192.168.1.102:6380@16380 slave f3c2... 0 1625000005000 6 connected
# 注释说明:
# 第一列为节点ID,第二列IP:端口,@后为集群总线端口
# 第三列角色(master/slave),最后为槽位分配
三、节点删除操作全流程
3.1 删除从节点(低风险操作)
假设我们要移除从节点192.168.1.102:6380:
# 步骤1:确认节点角色
$ redis-cli -h 192.168.1.102 -p 6380 role
# 输出应为"slave"
# 步骤2:在任意主节点执行遗忘命令
$ redis-cli -h 192.168.1.101 -p 6379 cluster forget a1b2...
# 注释:a1b2...为目标节点的ID
# 步骤3:等待60秒(超过cluster-node-timeout时间)
# 步骤4:停止目标节点服务
$ ssh 192.168.1.102
$ systemctl stop redis-6380.service
3.2 删除主节点(高风险操作)
要移除主节点192.168.1.103:6379,需先迁移其槽位:
# 步骤1:启动槽位迁移
$ redis-cli --cluster reshard 192.168.1.101:6379
# 交互式提示:
How many slots do you want to move? 16384/6≈2730
Destination node ID? # 选择其他主节点ID
Source node ID? # 输入待删除主节点ID
# 步骤2:验证迁移结果
$ redis-cli -h 192.168.1.103 -p 6379 cluster slots
# 应返回空数组
# 步骤3:执行节点下线
$ redis-cli --cluster del-node 192.168.1.101:6379 a1b2...
# 注释:最后参数为待删节点ID
# 步骤4:检查集群状态
$ redis-cli --cluster check 192.168.1.101:6379
# 确认所有槽位已重新分配且集群状态ok
四、常见问题与解决方案
4.1 节点状态始终显示"handshake"
现象:
$ cluster nodes
a1b2... 192.168.1.104:6379 handshake...
原因:节点间防火墙未开放集群总线端口(默认为客户端端口+10000)
解决:
# 检查防火墙规则
$ iptables -L -n | grep 16379
# 若无输出则添加规则
$ iptables -A INPUT -p tcp --dport 16379 -j ACCEPT
4.2 槽位迁移卡在"importing"状态
诊断命令:
$ redis-cli -h 故障节点 cluster nodes | grep importing
处理方案:
# 强制完成迁移
$ redis-cli -h 故障节点 cluster setslot <slot> stable
4.3 客户端出现MOVED重定向错误
典型日志:
-MOVED 1234 192.168.1.105:6379
优化措施:
# Python客户端连接示例(使用redis-py-cluster)
from rediscluster import RedisCluster
startup_nodes = [{"host": "192.168.1.101", "port": "6379"}]
rc = RedisCluster(
startup_nodes=startup_nodes,
decode_responses=True,
# 开启自动重定向
read_from_replicas=True
)
五、技术方案深度分析
5.1 应用场景对比
操作类型 | 适用场景 | 耗时预估 |
---|---|---|
从节点直接删除 | 紧急硬件下线 | <2分钟 |
主节点槽迁移 | 计划性缩容 | 10-30分钟 |
5.2 优缺点总结
优势:
- 无损服务:通过槽位迁移实现业务零感知
- 精确控制:支持按节点/槽位粒度操作
局限性:
- 迁移过程占用网络带宽(建议不超过1Gbps)
- 批量操作时需顺序执行(Redis Cluster暂不支持并行迁移)
六、关键注意事项
时间窗口选择:
- 避免业务高峰时段操作
- 设置
cluster-node-timeout 15000
(默认15秒超时)
数据安全措施:
# 操作前创建快照 $ redis-cli -h 待删节点 save # 备份节点配置文件 $ cp redis.conf redis.conf.bak.$(date +%s)
客户端适配:
// JedisCluster示例(Java) JedisCluster jc = new JedisCluster( new HostAndPort("192.168.1.101", 6379), 2000, // 超时时间 100, // 最大重试次数 new GenericObjectPoolConfig<>() );
七、关联技术解析:集群总线协议
Redis Cluster使用两种端口:
- 客户端端口(默认6379)
- 集群总线端口(客户端端口+10000)
总线协议负责:
- 故障检测(PING/PONG机制)
- 配置信息传播(Gossip协议)
- 故障转移协调
# 查看总线通信状态
$ tcpdump -i eth0 -nn 'port 16379' -c 100
# 输出示例:
IP 192.168.1.101.16379 > 192.168.1.102.16379: Flags [P], seq 1:100
八、总结与建议
通过某电商平台的实战数据,在正确操作下:
- 从节点删除成功率可达100%
- 主节点删除操作平均耗时23分钟
- 故障率从初期35%降至3%以下(通过完善操作流程)
建议每次操作后执行以下检查清单:
redis-cli --cluster check
集群完整性redis-cli info stats
查看ops变化- 客户端日志搜索MOVED/ASK错误