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 "扩容完成!"

七、结语

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

相关推荐
m0_6138562933 分钟前
mysql如何利用事务隔离级别解决特定业务冲突_mysql隔离方案选型
jvm·数据库·python
Adios79444 分钟前
VPR:Pitts50K和Norland数据集下载
数据库
东风破1371 小时前
DM用户权限、表、约束等对象的基本操作,SQL日志的开启介绍
数据库·sql·dm达梦数据库
收获不止数据库1 小时前
达梦9发布会归来:AI 时代,我们需要一款什么样的数据库?
数据库·人工智能·ai·语言模型·数据分析
小宇的天下1 小时前
Virtuoso GUI 界面中的关键模块定义
数据库
bqq198610261 小时前
MySQL 5.7 与 MySQL 8.0 的主要区别
数据库·mysql
Elastic 中国社区官方博客2 小时前
Elastic-caveman : 在不损失 Elastic 最佳效果的情况下,将 AI 响应 tokens 减少64%
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·全文检索
Deepincode2 小时前
Redis源码探究系列—跳表(skiplist)源码实现详解
redis
互联网推荐官2 小时前
上海软件定制开发全流程拆解:需求分析、技术选型与交付管理的工程实践
大数据·数据库·需求分析
专注API从业者3 小时前
Open Claw 京东商品监控选品实战:一键抓取、实时监控、高效选品
java·服务器·数据库