前面介绍了Redis 主从模式
、哨兵模式
,以及他们的优缺点,今天我们来介绍集群模式
。
首先我们来看下为什么要引入集群模式
:虽然哨兵模式解决了可用性问题,但无法解决可扩展性问题。
Redis Cluster是Redis的分布式解决方案,在3.0版本正式推出,有效地解决了Redis分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用Cluster架构方案达到负载均衡的目的。
集群模式优点
- 分布式架构,支持数据分片:将数据自动分布在多个主节点上,每个主节点负责一部分哈希槽。
- 提升写能力和存储能力:多个主节点并行写,突破单机性能限制。
- 主从结合 + 自动故障转移:每个主节点可挂多个从节点,支持高可用。
- 水平扩展:可以添加更多节点,按需扩容。
分区算法
节点取余分区
使用特定的数据,如Redis的键或用户ID,再根据节点数量N使用公式: hash(key)%N
计算出哈希值,用来决定数据映射到哪一个节点上。这种方案存在一个问题:当节点数量变化时,如扩容或收缩节点,数据节点映射关系需要重新计算,会导致数据的重新迁移。
一致性哈希分区
一致性哈希分区( Distributed Hash Table)实现思路是为系统中每个节点分配一个 token,范围一般在0~23,这些token构成一个哈希环。数据读写执行节点查找操作时,先根据key计算hash值,然后顺时针找到第一个大于等于该哈希值的token节点。例如:
集群中有三个节点(Node1、Node2、Node3),五个键(key1、key2、key3、key4、key5),其路由规则为:
当集群中增加节点时,比如当在Node2和Node3之间增加了一个节点Node4,此时再访问节点key4时,不能在Node4中命中,更一般的,介于Node2和Node4之间的key均失效,这样的失效方式太过于"集中"和"暴力",更好的方式应该是"平滑"和"分散"地失效。

这种方式相比节点取余最大的好处在于加入和删除节点只影响哈希环中相邻的节点,对其他节点无影响。这也正是它的弊端,如上图所示,Node4
的增加仅对Node3
起作用,其他两个节点的负载没起到作用。
虚拟一致性哈希分区

为了在增删节点的时候,各节点能够保持动态的均衡,将每个真实节点虚拟出若干个虚拟节点,再将这些虚拟节点随机映射到环上。此时每个真实节点不再映射到环上,真实节点只是用来存储键值对,它负责接应各自的一组环上虚拟节点。当对键值对进行存取路由时,首先路由到虚拟节点上,再由虚拟节点找到真实的节点。
如下图所示,三个节点真实节点:Node1、Node2和Node3,每个真实节点虚拟出三个虚拟节点:X#V1、X#V2和X#V3,这样每个真实节点所负责的hash空间不再是连续的一段,而是分散在环上的各处,这样就可以将局部的压力均衡到不同的节点,虚拟节点越多,分散性越好,理论上负载就越倾向均匀。
虚拟槽分区
将整个 Key 空间划分为 多个虚拟槽(或虚拟节点),这些槽再映射到真实的 Redis 实例上。客户端或代理通过"虚拟槽"进行路由。
Redis数据分区
Redis Cluser采用虚拟槽分区,所有的键根据哈希函数映射到0 ~16383整数槽内,计算公式:slot=CRC16(key) &16383。每一个节点负责维护―部分槽以及槽所映射的键值数据。
搭建集群
我依然用docker搭建该集群,创建docker-compose.yml如下:
yml
version: '3.8'
services:
redis-7000:
image: redis:7.2.4
container_name: redis-7000
command: >
redis-server --port 7000 --bind 0.0.0.0 --cluster-enabled yes
--cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7000:7000"
- "17000:17000"
networks:
- redis-cluster-net
redis-7001:
image: redis:7.2.4
container_name: redis-7001
command: >
redis-server --port 7001 --bind 0.0.0.0 --cluster-enabled yes
--cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7001:7001"
- "17001:17001"
networks:
- redis-cluster-net
redis-7002:
image: redis:7.2.4
container_name: redis-7002
command: >
redis-server --port 7002 --bind 0.0.0.0 --cluster-enabled yes
--cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7002:7002"
- "17002:17002"
networks:
- redis-cluster-net
redis-7003:
image: redis:7.2.4
container_name: redis-7003
command: >
redis-server --port 7003 --bind 0.0.0.0 --cluster-enabled yes
--cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7003:7003"
- "17003:17003"
networks:
- redis-cluster-net
redis-7004:
image: redis:7.2.4
container_name: redis-7004
command: >
redis-server --port 7004 --bind 0.0.0.0 --cluster-enabled yes
--cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7004:7004"
- "17004:17004"
networks:
- redis-cluster-net
redis-7005:
image: redis:7.2.4
container_name: redis-7005
command: >
redis-server --port 7005 --bind 0.0.0.0 --cluster-enabled yes
--cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
ports:
- "7005:7005"
- "17005:17005"
networks:
- redis-cluster-net
networks:
redis-cluster-net:
driver: bridge
启动方式:
bash
docker-compose up -d
手动执行集群创建命令:
bash
# Redis 默认会把 16384 个槽平均分配给所有的主节点
# --cluster-replicas 0 所有节点都做主节点(无从节点)
# --cluster-replicas 1 每个主节点有 1 个从节点(最常见)
# --cluster-replicas 2 每个主节点配 2 个从节点(更高可用,但需更多节点)
# 主节点1(负责 slot 0~5460) ← 从节点A
# 主节点2(负责 slot 5461~10922) ← 从节点B
# 主节点3(负责 slot 10923~16383) ← 从节点C
docker exec -it redis-7000 redis-cli --cluster create \
redis-7000:7000 redis-7001:7001 redis-7002:7002 \
redis-7003:7003 redis-7004:7004 redis-7005:7005 \
--cluster-replicas 1
端口 | 用途 |
---|---|
7000~7005 | Redis 服务端口 |
17000~17005 | Redis Cluster 节点间通信(内部端口) |

bash
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica redis-7004:7004 to redis-7000:7000
Adding replica redis-7005:7005 to redis-7001:7001
Adding replica redis-7003:7003 to redis-7002:7002
M: dc380ddd87512d431a276f65574d77437e58ec4c redis-7000:7000
slots:[0-5460] (5461 slots) master
M: 5af076975f4e6354b9d2ac88acd67db1d4ee261b redis-7001:7001
slots:[5461-10922] (5462 slots) master
M: 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b redis-7002:7002
slots:[10923-16383] (5461 slots) master
S: b871db12126991bd32ebf62bbc8b4df1ba0bb4cb redis-7003:7003
replicates 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
S: 73185f95749f878d2d4f7265fe761f5adc994425 redis-7004:7004
replicates dc380ddd87512d431a276f65574d77437e58ec4c
S: 9fee6150d3aee9f62ed4b239f30a9ba4baa727df redis-7005:7005
replicates 5af076975f4e6354b9d2ac88acd67db1d4ee261b
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node redis-7000:7000)
M: dc380ddd87512d431a276f65574d77437e58ec4c redis-7000:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004
slots: (0 slots) slave
replicates dc380ddd87512d431a276f65574d77437e58ec4c
S: 9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005
slots: (0 slots) slave
replicates 5af076975f4e6354b9d2ac88acd67db1d4ee261b
S: b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003
slots: (0 slots) slave
replicates 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
docker中的运行情况
查看集群节点信息
bash
E:\CK\learn\docker\redis\cluster>docker exec -it redis-7000 redis-cli -p 7000 cluster nodes
5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001@17001 master - 0 1754448154826 2 connected 5461-10922
dc380ddd87512d431a276f65574d77437e58ec4c 172.20.0.6:7000@17000 myself,master - 0 1754448153000 1 connected 0-5460
41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002@17002 master - 0 1754448153000 3 connected 10923-16383
73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004@17004 slave dc380ddd87512d431a276f65574d77437e58ec4c 0 1754448153821 1 connected
9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005@17005 slave 5af076975f4e6354b9d2ac88acd67db1d4ee261b 0 1754448153000 2 connected
b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003@17003 slave 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 0 1754448154524 3 connected
bash
# key1 应该在7001分片的槽位上,在7000上执行会提示error信息
127.0.0.1:7000> set key1 value1
(error) MOVED 9189 172.20.0.3:7001
127.0.0.1:7000> set key2 value2
OK
校验槽位
依据下面的槽位分配信息可以看出,14687 位于master[2],第三分片处,当我们执行set mykey myvalue
的时候可以看到提示需要到7002
分片执行该命令。
bash
# Master[0] -> Slots 0 - 5460
# Master[1] -> Slots 5461 - 10922
# Master[2] -> Slots 10923 - 16383
C:\Users\86158>docker exec -it redis-7000 redis-cli -p 7000
127.0.0.1:7000> cluster keyslot mykey
(integer) 14687
127.0.0.1:7000> set mykey myvalue
(error) MOVED 14687 172.20.0.7:7002
如何解决上面的问题?需要在启动redis-cli的时候加入-c
,具体如下(我启动7001
分片,执行上述命令):
bash
C:\Users\86158>docker exec -it redis-7001 redis-cli -c -p 7001
127.0.0.1:7001> set mykey myvalue
-> Redirected to slot [14687] located at 172.20.0.7:7002
OK
172.20.0.7:7002> get mykey
"myvalue"
172.20.0.7:7002>
不平均分配槽位
手动分配槽位
bash
# 将槽 0 分配给 Node A(不推荐这种槽位很少的情况,容易造成热点key)
redis-cli -p 7000 cluster addslots 0
# 将槽 1~8191 分配给 Node B
redis-cli -p 7001 cluster addslots $(seq 1 8191)
# 将槽 8192~16383 分配给 Node C
redis-cli -p 7002 cluster addslots $(seq 8192 16383)
集群扩缩容
扩容
bash
# 切记这里 'cluster_redis-cluster-net' 比前面 docker-compose.yml 文件中的网络名称多了一个
'cluster_'前缀,这是因为docker默认会把项目名称作为前缀导致,可用 'docker network ls' 查看当前网络
# 1.启动新节点 redis-7006
docker run -d --name redis-7006 -p 7006:7006 -p 17006:17006 --net cluster_redis-cluster-net redis:7.2.4 redis-server --port 7006 --bind 0.0.0.0 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --cluster-announce-ip 192.168.10.11 --cluster-announce-port 7006 --cluster-announce-bus-port 17006 --appendonly yes
# 2.将 redis-7006 加入集群
docker exec -it redis-7006 redis-cli --cluster add-node 192.168.10.11:7006 192.168.10.11:7000
# 3.查看集群节点
docker exec -it redis-7006 redis-cli -p 7006 cluster nodes
bash
E:\CK\learn\docker\redis\cluster>docker exec -it redis-7006 redis-cli --cluster add-node 192.168.10.11:7006 192.168.10.11:7000
>>> Adding node 192.168.10.11:7006 to cluster 192.168.10.11:7000
>>> Performing Cluster Check (using node 192.168.10.11:7000)
M: dc380ddd87512d431a276f65574d77437e58ec4c 192.168.10.11:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: 5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004
slots: (0 slots) slave
replicates dc380ddd87512d431a276f65574d77437e58ec4c
S: 9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005
slots: (0 slots) slave
replicates 5af076975f4e6354b9d2ac88acd67db1d4ee261b
S: b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003
slots: (0 slots) slave
replicates 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Getting functions from cluster
>>> Send FUNCTION LIST to 192.168.10.11:7006 to verify there is no functions in it
>>> Send FUNCTION RESTORE to 192.168.10.11:7006
>>> Send CLUSTER MEET to node 192.168.10.11:7006 to make it join the cluster.
[OK] New node added correctly.
bash
# 执行 查看节点信息
docker exec -it redis-7000 redis-cli -p 7000 cluster nodes
# 获取到7006节点信息
f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006@17006 master - 0 1754448460000 0 connected

字段 | 含义 |
---|---|
f7ccfb11261c098814cf3f2cda07ccf6175b46f0 |
节点 ID |
192.168.10.11:7006@17006 |
节点 IP:端口,@17006 是集群总线端口(用于节点之间的通信) |
master |
节点角色(master / slave / myself / fail 等) |
- |
如果是 slave,这里会是 master 的节点 ID;master 则为 - |
0 |
ping_sent:上一次发送 PING 的时间戳(ms) |
1754448460000 |
pong_recv:上一次接收到 PONG 的时间戳(ms) |
0 ✅ |
config_epoch:配置纪元(Config Epoch),用于 Redis 集群中的主节点冲突判定 |
connected |
与该节点的连接状态 |
自动分配槽位(rebalance:根据槽位数量自动平均分配)
bash
# 重新分配槽位:由于槽位目前被三个节点平均分配,所以每个节点会分配给7006大概1366/1365个槽位以达到新的平衡
docker exec -it redis-7000 redis-cli --cluster rebalance 127.0.0.1:7000 --cluster-use-empty-masters
>>> Performing Cluster Check (using node 127.0.0.1:7000)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Rebalancing across 4 nodes. Total weight = 4.00
Moving 1366 slots from 172.20.0.7:7001 to 192.168.10.11:7006

bash
E:\CK\learn\docker\redis\cluster>docker exec -it redis-7000 redis-cli -p 7000 cluster nodes
5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001@17001 master - 0 1754451200360 2 connected 6827-10922
dc380ddd87512d431a276f65574d77437e58ec4c 172.20.0.6:7000@17000 myself,master - 0 1754451199000 1 connected 1365-5460
41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002@17002 master - 0 1754451199857 3 connected 12288-16383
73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004@17004 slave dc380ddd87512d431a276f65574d77437e58ec4c 0 1754451198550 1 connected
9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005@17005 slave 5af076975f4e6354b9d2ac88acd67db1d4ee261b 0 1754451199000 2 connected
b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003@17003 slave 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 0 1754451199000 3 connected
f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006@17006 master - 0 1754451199561 7 connected 0-1364 5461-6826 10923-12287
手动分配槽位(reshard:将槽位从一个节点迁移到另一个节点)
bash
docker exec -it redis-7000 redis-cli --cluster reshard 192.168.10.11:7000
>>> Performing Cluster Check (using node 192.168.10.11:7000)
M: dc380ddd87512d431a276f65574d77437e58ec4c 192.168.10.11:7000
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
M: 5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001
slots:[6827-10922] (4096 slots) master
1 additional replica(s)
M: 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
S: 73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004
slots: (0 slots) slave
replicates dc380ddd87512d431a276f65574d77437e58ec4c
S: 9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005
slots: (0 slots) slave
replicates 5af076975f4e6354b9d2ac88acd67db1d4ee261b
S: b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003
slots: (0 slots) slave
replicates 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
M: f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# 输入要迁移的槽位个数:'10'
How many slots do you want to move (from 1 to 16384)? 10
# 此处需要黏贴目标节点Id:'f7ccfb11261c098814cf3f2cda07ccf6175b46f0'
What is the receiving node ID? f7ccfb11261c098814cf3f2cda07ccf6175b46f0
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
# 这里选择all,平均分配,
#当然这里可以选择某一个或者几个节点id,然后输入done,此时7006的槽位将从这一个或几个节点分配
Source node #1: all
Ready to move 10 slots.
Source nodes:
M: dc380ddd87512d431a276f65574d77437e58ec4c 192.168.10.11:7000
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
M: 5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001
slots:[6827-10922] (4096 slots) master
1 additional replica(s)
M: 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
Destination node:
M: f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006
slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
Resharding plan:
Moving slot 1365 from dc380ddd87512d431a276f65574d77437e58ec4c
Moving slot 1366 from dc380ddd87512d431a276f65574d77437e58ec4c
Moving slot 1367 from dc380ddd87512d431a276f65574d77437e58ec4c
Moving slot 1368 from dc380ddd87512d431a276f65574d77437e58ec4c
Moving slot 6827 from 5af076975f4e6354b9d2ac88acd67db1d4ee261b
Moving slot 6828 from 5af076975f4e6354b9d2ac88acd67db1d4ee261b
Moving slot 6829 from 5af076975f4e6354b9d2ac88acd67db1d4ee261b
Moving slot 12288 from 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
Moving slot 12289 from 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
Moving slot 12290 from 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
Do you want to proceed with the proposed reshard plan (yes/no)? yes
Moving slot 1365 from 192.168.10.11:7000 to 192.168.10.11:7006:
Moving slot 1366 from 192.168.10.11:7000 to 192.168.10.11:7006:
Moving slot 1367 from 192.168.10.11:7000 to 192.168.10.11:7006:
Moving slot 1368 from 192.168.10.11:7000 to 192.168.10.11:7006:
Moving slot 6827 from 172.20.0.7:7001 to 192.168.10.11:7006:
Moving slot 6828 from 172.20.0.7:7001 to 192.168.10.11:7006:
Moving slot 6829 from 172.20.0.7:7001 to 192.168.10.11:7006:
Moving slot 12288 from 172.20.0.4:7002 to 192.168.10.11:7006:
Moving slot 12289 from 172.20.0.4:7002 to 192.168.10.11:7006:
Moving slot 12290 from 172.20.0.4:7002 to 192.168.10.11:7006:
# 再次查看集群内槽位的分配信息,此时 可以查看 均有变化
E:\CK\learn\docker\redis\cluster>docker exec -it redis-7000 redis-cli -p 7000 cluster nodes
5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001@17001 master - 0 1754451341565 2 connected 6830-10922
dc380ddd87512d431a276f65574d77437e58ec4c 172.20.0.6:7000@17000 myself,master - 0 1754451340000 1 connected 1369-5460
41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002@17002 master - 0 1754451340560 3 connected 12291-16383
73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004@17004 slave dc380ddd87512d431a276f65574d77437e58ec4c 0 1754451341000 1 connected
9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005@17005 slave 5af076975f4e6354b9d2ac88acd67db1d4ee261b 0 1754451342270 2 connected
b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003@17003 slave 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 0 1754451342000 3 connected
f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006@17006 master - 0 1754451342000 7 connected 0-1368 5461-6829 10923-12290
缩容
可以利用手动分配槽位,将某个节点的槽位分配给其他节点:
bash
C:\Users\86158>docker exec -it redis-7000 redis-cli --cluster reshard 192.168.10.11:7000
>>> Performing Cluster Check (using node 192.168.10.11:7000)
M: dc380ddd87512d431a276f65574d77437e58ec4c 192.168.10.11:7000
slots:[1369-5460] (4092 slots) master
1 additional replica(s)
M: 5af076975f4e6354b9d2ac88acd67db1d4ee261b 172.20.0.7:7001
slots:[6830-10922] (4093 slots) master
1 additional replica(s)
M: 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b 172.20.0.4:7002
slots:[12291-16383] (4093 slots) master
1 additional replica(s)
S: 73185f95749f878d2d4f7265fe761f5adc994425 172.20.0.5:7004
slots: (0 slots) slave
replicates dc380ddd87512d431a276f65574d77437e58ec4c
S: 9fee6150d3aee9f62ed4b239f30a9ba4baa727df 172.20.0.3:7005
slots: (0 slots) slave
replicates 5af076975f4e6354b9d2ac88acd67db1d4ee261b
S: b871db12126991bd32ebf62bbc8b4df1ba0bb4cb 172.20.0.2:7003
slots: (0 slots) slave
replicates 41d45aa58cb102ce6dc4a6255f3aa5277c32ed6b
M: f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006
slots:[0-1368],[5461-6829],[10923-12290] (4106 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
#
How many slots do you want to move (from 1 to 16384)? 4106
What is the receiving node ID? dc380ddd87512d431a276f65574d77437e58ec4c
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1: f7ccfb11261c098814cf3f2cda07ccf6175b46f0
Source node #2: done
Ready to move 4106 slots.
Source nodes:
M: f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006
slots:[0-1368],[5461-6829],[10923-12290] (4106 slots) master
Destination node:
M: dc380ddd87512d431a276f65574d77437e58ec4c 192.168.10.11:7000
slots:[1369-5460] (4092 slots) master
1 additional replica(s)
Resharding plan:
............
............
查看 7006
节点信息
bash
# cluster nodes
# 此时再看7006节点已经变成了从节点(7000的从节点,可以 info replication 查看)
f7ccfb11261c098814cf3f2cda07ccf6175b46f0 192.168.10.11:7006@17006 slave dc380ddd87512d431a276f65574d77437e58ec4c 0 1754455116564 8 connected
从集群中忘记该节点
bash
# 集群中的所有节点忘记7006 其他节点均需要执行 cluster forget 操作(7001、7002、7003、7004、7005)
redis-cli -p 7000 cluster forget f7ccfb11261c098814cf3f2cda07ccf6175b46f0
# 进入7006 执行reset 退出集群
redis-cli -p 7006 cluster reset
# 如果docker运行的 则可删除该容器
docker stop redis-7006
docker rm redis-7006
节点之间通信
Redis Cluster 节点之间使用 Gossip 协议进行通信,通信方式:每个节点每 100 毫秒与部分节点交换心跳(ping/pong),通过这些消息同步集群状态(谁是 master,谁持有哪些槽等)。多个节点发现某个 master 不可达(ping 超时),标记为 PFAIL(疑似下线)超过半数 master 节点确认该节点挂掉 → 标记为 FAIL;它的某个从节点会自动被提升为新的 master。
配置纪元(Config Epoch)
每个节点有一个配置纪元,用来识别哪个节点对槽位的"声明"是最新的。
- 配置纪元越大,越优先成为槽位拥有者
- 防止网络分区等场景下的主从混乱
集群核心命令
命令 | 作用 |
---|---|
CLUSTER NODES |
查看集群所有节点信息 |
CLUSTER SLOTS |
查看槽位分布 |
CLUSTER INFO |
查看集群健康状态 |
CLUSTER FORGET <node-id> |
忘记指定节点(清理残留) |
CLUSTER REPLICATE <node-id> |
设置当前节点为某节点的从节点 |
CLUSTER RESET |
重置当前节点的集群状态 |
--cluster reshard |
手动迁移槽位 |
--cluster rebalance |
自动平均槽位 |
集群模式弊端
- 部署复杂:需要理解 slot 分片、节点通信、选主机制。
- 不支持多 key 跨 slot 操作(除非 hash tags):部分命令使用有限制。
- 客户端需支持 cluster 协议:不能用普通 Redis 客户端直连。
- 配置复杂,监控难度高。
各种模式优缺点比较
模式 | 是否高可用 | 是否支持分片 | 写能力 | 运维复杂度 | 自动故障转移 |
---|---|---|---|---|---|
主从模式 | ❌(手动切) | ❌(全量备份) | 低(单主) | 简单 | ❌ |
哨兵模式 | ✅(自动切) | ❌ | 低(单主) | 中等 | ✅ |
集群模式 | ✅ | ✅(16384槽) | 高(多主) | 高 | ✅ |