Redis分片集群伸缩

一、前言:为什么需要伸缩?

随着业务增长,你的 Redis Cluster 可能面临:

  • 容量不足:内存使用率 > 80%
  • 性能瓶颈:单节点 QPS 超过 8万
  • 资源浪费:低峰期节点闲置

Redis Cluster 支持在线伸缩(无需停机) ,通过 插槽(Slot)迁移 实现数据重平衡。

本文将手把手演示:

如何安全扩容 (新增主从节点)

如何优雅缩容 (下线节点并迁移数据)

全程业务无感知!


二、环境准备

2.1 当前集群状态(3 主 3 从)

节点 端口 角色 负责 Slot
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:启动新节点

创建配置目录
bash 复制代码
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

启动节点
bash 复制代码
redis-server /opt/redis-cluster/7007/redis.conf
redis-server /opt/redis-cluster/7008/redis.conf

此时新节点是孤立节点,未加入集群。


3.2 步骤 2:将新主节点加入集群

bash 复制代码
# 任选一个现有节点执行
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:集群中任意现有节点

验证

bash 复制代码
redis-cli -p 7001 cluster nodes
# 应看到 7007 节点,角色为 master,但 slots 为空

3.3 步骤 3:将新从节点挂到新主

bash 复制代码
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

bash 复制代码
redis-cli -p 7007 cluster myid

验证

bash 复制代码
redis-cli -p 7001 cluster nodes | grep 7008
# 应显示:slave <7007-node-id>

3.4 步骤 4:迁移插槽(重平衡数据)

方法一:自动重平衡(推荐)
bash 复制代码
redis-cli --cluster rebalance 192.168.1.10:7001 \
  --cluster-use-empty-masters \  # 允许空主参与分配
  --cluster-threshold 1          # 最小不平衡比例(%)
方法二:手动指定迁移量
bash 复制代码
# 从每个老主迁移 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 自动处理)

验证迁移结果

bash 复制代码
redis-cli -p 7001 cluster slots
# 应看到 7007 负责部分 slot(如 0-1000, 5461-6461, ...)

四、第二部分:在线缩容(安全下线节点)

目标 :下线 node3(7003) 及其从节点 node6(7006)

4.1 步骤 1:迁移 node3 的所有插槽

bash 复制代码
# 查看 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)

bash 复制代码
# 在主节点执行 forget
redis-cli -p 7001 cluster forget <7006-node-id>

# 停止 7006 进程
kill $(pgrep -f "7006")

⚠️ 必须先 forget 再 kill,否则集群会尝试重连。


4.3 步骤 3:下线主节点(7003)

确认其 slots 已清空:

bash 复制代码
redis-cli -p 7003 cluster nodes | grep myself
# 应显示:connected(无 slot 范围)

执行下线:

bash 复制代码
# 在其他节点 forget
redis-cli -p 7001 cluster forget <7003-node-id>

# 停止进程
kill $(pgrep -f "7003")

最终验证

bash 复制代码
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
  • ❌ 不要在高峰期执行大规模迁移
  • ✅ 迁移后验证数据一致性(抽样比对)

六、自动化脚本示例(扩容)

bash 复制代码
#!/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 "扩容完成!"

七、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
阿贵---2 小时前
实战:用Python开发一个简单的区块链
jvm·数据库·python
谪星·阿凯2 小时前
SQL注入漏洞进阶篇:从盲注到WAF绕过的全面解析
数据库·sql·计算机网络
快乐柠檬不快乐2 小时前
使用Python操作文件和目录(os, pathlib, shutil)
jvm·数据库·python
V1ncent Chen3 小时前
SQL大师之路 13 聚合函数和分组
数据库·sql·mysql·数据分析
赵渝强老师3 小时前
【赵渝强老师】高斯数据库(openGauss)的体系架构
数据库·postgresql·opengauss·gaussdb·国产数据库
IvorySQL3 小时前
开源同行,感谢有你|IvorySQL 社区邀您领取贡献者证书
数据库·postgresql·开源
IvorySQL3 小时前
PostgreSQL 技术日报 (3月19日)|当 AI 代理开始批量创建数据库
数据库·postgresql·开源
2401_874732533 小时前
Python上下文管理器(with语句)的原理与实践
jvm·数据库·python
l1t4 小时前
与系统库同名python脚本文件引起的奇怪错误及其解决
开发语言·数据库·python