一、前言:为什么需要伸缩?
随着业务增长,你的 Redis Cluster 可能面临:
- ❌ 容量不足:内存使用率 > 80%
- ❌ 性能瓶颈:单节点 QPS 超过 8万
- ❌ 资源浪费:低峰期节点闲置
Redis Cluster 支持在线伸缩(无需停机),通过 插槽(Slot)迁移 实现数据重平衡。
本文将手把手演示:
✅ 如何安全扩容(新增主从节点)
✅ 如何优雅缩容(下线节点并迁移数据)
✅ 全程业务无感知!
二、环境准备
2.1 当前集群状态(3 主 3 从)
| node1 | 7001 | master | 0–5460 |
| node2 | 7002 | master | 5461–10922 |
| node3 | 7003 | master | 10923–16383 |
| node4 | 7004 | slave | → node1 |
| node5 | 7005 | slave | → node2 |
| node6 | 7006 | slave | → node3 |
2.2 目标
- 扩容:新增 node7(7007) 主 + node8(7008) 从,接管部分 slot
- 缩容:下线 node3(7003),将其 slot 迁移至其他节点
💡 前提:已搭建 Redis Cluster(参考前文《Redis 搭建分片集群》)
三、第一部分:在线扩容(新增主从节点)
3.1 步骤 1:启动新节点
创建配置目录
mkdir -p /opt/redis-cluster/{7007,7008}
配置 redis.conf(以 7007 为例)
port 7007
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 15000
appendonly yes
protected-mode no
bind 0.0.0.0
daemonize yes
dir /opt/redis-cluster/7007
⚠️ 注意:7008 配置类似,仅改端口和 dir
启动节点
redis-server /opt/redis-cluster/7007/redis.conf
redis-server /opt/redis-cluster/7008/redis.conf
此时新节点是孤立节点,未加入集群。
3.2 步骤 2:将新主节点加入集群
# 任选一个现有节点执行
redis-cli –cluster add-node 192.168.1.10:7007 192.168.1.10:7001
- 192.168.1.10:7007:新主节点
- 192.168.1.10:7001:集群中任意现有节点
✅ 验证:
redis-cli -p 7001 cluster nodes
# 应看到 7007 节点,角色为 master,但 slots 为空
3.3 步骤 3:将新从节点挂到新主
redis-cli –cluster add-node \\
–cluster-slave \\
–cluster-master-id <7007的node-id> \\
192.168.1.10:7008 \\
192.168.1.10:7001
🔑 如何获取 node-id?
redis-cli -p 7007 cluster myid
✅ 验证:
redis-cli -p 7001 cluster nodes | grep 7008
# 应显示:slave <7007-node-id>
3.4 步骤 4:迁移插槽(重平衡数据)
方法一:自动重平衡(推荐)
redis-cli –cluster rebalance 192.168.1.10:7001 \\
–cluster-use-empty-masters \\ # 允许空主参与分配
–cluster-threshold 1 # 最小不平衡比例(%)
方法二:手动指定迁移量
# 从每个老主迁移 1000 个 slot 到 7007
redis-cli –cluster reshard 192.168.1.10:7001
交互式输入:
- How many slots do you want to move? → 3000
- What is the receiving node ID? → <7007-node-id>
- Source node IDs → 输入 all(从所有主节点匀出)
⏱️ 迁移过程:
- 客户端可能收到 ASK 重定向
- 业务无中断(Lettuce/Jedis 自动处理)
✅ 验证迁移结果:
redis-cli -p 7001 cluster slots
# 应看到 7007 负责部分 slot(如 0-1000, 5461-6461, …)
四、第二部分:在线缩容(安全下线节点)
目标:下线 node3(7003) 及其从节点 node6(7006)
4.1 步骤 1:迁移 node3 的所有插槽
# 查看 node3 负责的 slot 范围
redis-cli -p 7003 cluster nodes | grep myself
# 输出示例:… master – 0-0 3 connected 10923-16383
# 将其 slot 全部迁移到 node1(7001)
redis-cli –cluster reshard 192.168.1.10:7001
交互输入:
- slots to move: 5461(16383 – 10923 + 1 = 5461)
- receiving node ID: <7001-node-id>
- source node ID: <7003-node-id>
- done
✅ 关键:确保迁移完成后再下线!
4.2 步骤 2:下线从节点(7006)
# 在主节点执行 forget
redis-cli -p 7001 cluster forget <7006-node-id>
# 停止 7006 进程
kill $(pgrep -f "7006")
⚠️ 必须先 forget 再 kill,否则集群会尝试重连。
4.3 步骤 3:下线主节点(7003)
确认其 slots 已清空:
redis-cli -p 7003 cluster nodes | grep myself
# 应显示:connected(无 slot 范围)
执行下线:
# 在其他节点 forget
redis-cli -p 7001 cluster forget <7003-node-id>
# 停止进程
kill $(pgrep -f "7003")
✅ 最终验证:
redis-cli -p 7001 cluster nodes
# 应不再显示 7003 和 7006
五、客户端影响与最佳实践
5.1 业务是否中断?
- 扩容/缩容期间:
- 写操作:可能短暂延迟(slot 迁移中)
- 读操作:自动重定向(MOVED/ASK)
- 现代客户端(Lettuce/Jedis)自动处理,应用层无感知
5.2 生产环境建议
| 扩容时机 | 内存使用率 > 70%,或 CPU 持续 > 80% |
| 迁移速度 | 使用 –cluster-timeout 控制(避免网络打满) |
| 监控指标 | 关注 migrate_cached_sockets, evicted_keys |
| 回滚方案 | 迁移前备份 AOF/RDB |
5.3 避免踩坑
- ❌ 不要直接 kill 节点(先 forget)
- ❌ 不要在高峰期执行大规模迁移
- ✅ 迁移后验证数据一致性(抽样比对)
六、自动化脚本示例(扩容)
#!/bin/bash
# auto_expand.sh
NEW_MASTER_PORT=7009
NEW_SLAVE_PORT=7010
EXISTING_NODE="192.168.1.10:7001"
# 1. 启动新节点(略)
# 2. 加入集群
redis-cli –cluster add-node 192.168.1.10:$NEW_MASTER_PORT $EXISTING_NODE
MASTER_ID=$(redis-cli -p $NEW_MASTER_PORT cluster myid)
redis-cli –cluster add-node \\
–cluster-slave \\
–cluster-master-id $MASTER_ID \\
192.168.1.10:$NEW_SLAVE_PORT \\
$EXISTING_NODE
# 3. 自动重平衡
redis-cli –cluster rebalance $EXISTING_NODE –cluster-use-empty-masters
echo "扩容完成!"
七、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!



