Redis集群的创建、剔除节点与新增节点操作过程原创
# 一、集群创建
# 1. 准备工作
版本选择是第一步。不同安装方式拿到的版本差异很大:
版本说明
本文写于 2024-06,2026-08 重写。
关键版本差异:Redis 5.0 起 --cluster 子命令取代 redis-trib.rb;6.0 起支持 ACL;7.0 新增 sharded pub/sub。
本文命令基于 Redis 6.x/7.x,旧版(5.x 以下)部分命令不兼容。
| 安装方式 | 拿到的版本 | 适用场景 |
|---|---|---|
apt-get install redis-server (Ubuntu 20.04) | 5.0.7 | ⚠️ 太旧,不推荐用于新集群 |
apt-get install redis-server (Ubuntu 22.04) | 6.0.16 | 可用,但不是最新 |
| 从源码编译 / 官方仓库 | 7.x | ✅ 推荐 |
# 推荐:从官方源码编译安装 Redis 7.x
wget http://download.redis.io/releases/redis-7.2.4.tar.gz -P /opt
cd /opt && tar xzf redis-7.2.4.tar.gz
cd redis-7.2.4 && make && make install
# 验证版本
redis-server --version
redis-cli --version
2
3
4
5
6
7
8
所有节点的 redis.conf 必须开启集群模式:
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
2
3
4
cluster-node-timeout这里用 5000,是为了让实验环境里的故障转移快点看到结果。生产上建议按 Redis 集群部署 的 15000 走:这个值既是判定节点失联的门槛,也是故障转移的最短耗时量级,调小虽然转移更快,但跨机房或网络有抖动时很容易误判成主节点失联、触发无谓的切换。
# 2. 创建集群
启动所有实例后,使用 redis-cli 创建集群:
redis-cli --cluster create \
<node1>:6379 <node2>:6379 <node3>:6379 \
<node4>:6379 <node5>:6379 <node6>:6379 \
--cluster-replicas 1
2
3
4
为什么这么摆:--cluster-replicas 1 表示每个主节点有一个从节点。6 个节点会被分配成 3 主 3 从,这是生产环境的最小可用形态(2 主凑不出故障转移所需的多数派)。
# 二、剔除节点
# 1. 识别要剔除的节点
redis-cli -c -h <any-node> cluster nodes
输出中每行的格式:<node-id> <ip:port>@<cport> <flags> <master-id> <ping-sent> <pong-recv> <config-epoch> <link-state> <slot-range>。记录要剔除节点的 node-id(第一列 40 位十六进制字符串)。
# 2. 迁移槽位(仅对主节点)
如果要剔除的是主节点,必须先把槽位迁走,否则集群会进入不完整状态:
redis-cli --cluster reshard <any-node>:6379
按提示输入:
- 要迁移的槽位数量(建议全部迁走)
- 目标节点 node-id(从集群中选一个健康的)
- 源节点 node-id(要剔除的那个)
# 3. 从集群中移除节点
redis-cli -c -h <any-node> cluster forget <node-id>
⚠️ 关键坑:必须在每个节点上分别执行 cluster forget
Redis Cluster 使用 gossip 协议传播节点信息。如果只在一个节点上执行 forget,其他节点仍会通过 gossip 把该节点"重新学习"回来,导致节点"删不掉"。
正确做法:在每个主节点上依次执行上述命令,或者使用脚本批量执行:
# 获取所有主节点地址
MASTERS=$(redis-cli -h <any-node> -p 6379 cluster nodes | grep "master" | awk '{print $2}' | cut -d'@' -f1)
# 在每个主节点上执行 forget
for master in $MASTERS; do
redis-cli -h $(echo $master | cut -d':' -f1) -p $(echo $master | cut -d':' -f2) cluster forget <node-id>
done
2
3
4
5
6
7
原理:cluster forget 只在执行它的节点上生效,它不会广播到其他节点。gossip 的 MEET/PING/PONG 消息会携带已知节点列表,如果其他节点还记得被删节点,会通过 gossip 把它重新传播回来。
# 4. 关闭节点进程
redis-cli -h <node-host> -p <node-port> shutdown
# 三、添加新节点
# 1. 启动新节点
配置并启动一个新的 Redis 实例,确保 cluster-enabled yes 已开启。
# 2. 将新节点加入集群
作为主节点加入:
redis-cli --cluster add-node <new-node>:6379 <existing-node>:6379
作为从节点加入(指定主节点):
redis-cli --cluster add-node <new-node>:6379 <existing-node>:6379 \
--cluster-slave --cluster-master-id <master-node-id>
2
# 3. 重新分片(主节点需要)
新主节点加入后默认没有槽位,需要显式迁移:
redis-cli --cluster reshard <any-node>:6379
# 四、验证步骤(每条命令后都做)
# 4.1 确认集群状态健康
redis-cli -h <any-node> -p 6379 cluster info
关键字段判读:
| 字段 | 期望值 | 说明 |
|---|---|---|
cluster_state | ok | fail 表示有槽位未分配或多数主节点不可达 |
cluster_slots_assigned | 16384 | 所有槽位都已分配 |
cluster_slots_ok | 16384 | 所有槽位都正常 |
cluster_known_nodes | 实际节点数 | 新增/删除后核对 |
cluster_size | 主节点数 | 剔除主节点后应减少 |
# 4.2 确认槽位分布
redis-cli -h <any-node> -p 6379 cluster nodes
检查:
- 每个主节点(
master标识)都有非空的槽位范围(最后一列如0-5460) - 每个从节点(
slave标识)的master-id指向正确的主节点 - 无
fail?或fail状态的节点
# 4.3 集群完整性检查
redis-cli --cluster check <any-node>:6379
期望输出包含 [OK] All 16384 slots covered,无 [WARNING]。
# 4.4 数据读写验证
# 写入
redis-cli -c -h <any-node> -p 6379 set test_key "test_value"
# 读取(可能路由到其他节点)
redis-cli -c -h <any-node> -p 6379 get test_key
2
3
4
5
-c 参数让 redis-cli 自动处理 MOVED 重定向。
# 五、坑与边界
apt-get install redis-server版本过旧(5.x)。集群模式在 5.x 虽可用,但缺乏后续版本的稳定性修复和性能优化。生产环境请用官方源码或官方仓库安装 6.x/7.x。cluster forget只执行一次会失效。必须在每个节点上都执行,或通过脚本批量在所有主节点上执行。剔除主节点前必须先 reshard。直接
forget一个持有槽位的主节点会导致集群进入fail状态,该节点上的槽位变为不可访问。reshard 期间不要重启节点。槽位迁移是渐进式的,中途重启可能导致槽位处于
migrating/importing中间态,形成 open slots 故障(参考《Redis Cluster 新增节点 slot 迁移卡住故障复盘》)。新节点加入后默认无槽位。忘记 reshard 会导致新主节点成为"空主",集群状态虽为
ok,但新节点不会分担任何读写负载。gossip 传播有延迟。大型集群中,节点变更信息传播到所有节点可能需要数秒。执行
forget后立即检查cluster nodes可能仍看到被删节点,等待 5-10 秒后再确认。
🤖 Agent 可直接解析的元数据块(点击展开)
{
"_meta": {
"doc_version": "2026-08-25",
"article_id": "redis-cluster-management",
"profile_context": "any",
"estimated_setup_time": "30min"
},
"quick_start": {
"create": "redis-cli --cluster create node1:6379 node2:6379 ... --cluster-replicas 1",
"remove_master": "1) reshard 迁走槽位 2) 在每个主节点上 cluster forget <node-id> 3) shutdown",
"add_master": "redis-cli --cluster add-node new:6379 existing:6379 && redis-cli --cluster reshard existing:6379"
},
"safety_rules": [
"剔除主节点前必须先用 reshard 迁走全部槽位",
"cluster forget 必须在每个节点上分别执行,gossip 会重新传播",
"reshard 期间避免重启节点,防止 open slots",
"新主节点加入后必须 reshard 分配槽位"
],
"verification": {
"cluster_state": "cluster info | grep cluster_state 应返回 ok",
"slot_coverage": "cluster info | grep cluster_slots_assigned 应为 16384",
"integrity_check": "redis-cli --cluster check <node>:6379 应返回 [OK] All 16384 slots covered"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24