Redis哨兵简介
前文中提到了主从备份,但是主从集群如果出现故障怎么恢复呢?哨兵就是一个用于自动故障恢复的机制。
Redis哨兵(Sentinel)是Redis的高可用性解决方案,它能够监控Redis主从节点的运行状态,并在主节点发生故障时自动进行故障转移,将其中一个从节点提升为新的主节点,以保证Redis服务的连续性和高可用性。
哨兵的功能
首先,第一个功能就是监控。对于哨兵(sentinel)来说,他会不断检查一个主从集群的状态,看这个集群中的主节点和各个从节点之间是否在按照预期进行工作。
第二个功能是自动故障恢复,如果说主节点出现了问题,那么,哨兵sentinel就会提升一个从节点为新的主节点,即便是故障实例恢复之后也会以新的主节点为主。
最后一个功能是通知客户端,当集群发生故障后,Redis的这个sentinel就会作为一个Redis客户端的服务发现来源,把最新的消息推送到Redis的客户端上去。
哨兵的监控原理
监控是基于心跳机制来实现的。
哨兵Sentinel会每隔1s向集群中的每个实例发送一次ping命令。如果说Sentinel节点发现这个实例未有在规定的时间内响应,那么这个实例就会被认为是主观下线的。
如果,超过了一定数量的sentinel都认为这个实例主观下线了,那么这个实例就是客观下线了,这个“数量(quorum)”最好需要超过Sentinel实例数量的一半。
哨兵的故障恢复原理
一旦说这个主节点被Sentinel认为是客观下线了,故障了,那么,哨兵就会在从节点中选择一个新的节点做为一个新的主节点。
首先,sentinel会判断从节点与主节点断开时间的长短,如果超过了某个值(配置文件配置的),那么就排除掉这个从节点。
然后进一步的,判断从节点的slave-priority值(也是在配置文件中配置的),越小那么优先级越高,如果是0,永远不参加选举。
如果说slave-priority一样的话,那么就判断从节点的offset值,越大说明数据越新,优先级也越高。
最后,再判断从节点的运行id大小,越小那么优先级越高。
由此,选出来一个新的主节点,开始切换。
sentinel给这个新的主节点发送salveof no one的命令,让其真正成为新的主节点。
然后,sentinel会给其他的从节点发送slaveof new_masterIP port的命令,让这些老的从节点成为新主节点的从节点并开始同步数据。
最后,sentinel还会将故障节点,也就是老的主节点标记为从节点,当故障节点恢复之后,会自动成为新的主节点的从节点。
哨兵的通知
通知也是哨兵的最后一个任务,哨兵会将新的主节点的连接信息发送给其他从节点建立新的连接(这是前文提到的)。
在此基础上,还要将新的主节点的连接信息,通知所有的客户端,将读写请求转移到以新master为核心的新集群上去。
带有哨兵的Redis集群实现
以一个简约的高可用的集群模式为例进行实现,即一主二从三哨兵。
首先确保有redis镜像。并建立三个redis容器。且哨兵的前置条件是主从复制ok。如图为一个一主二从的主从复制的redis:

1
| docker pull redis:bullseye
|
设置好需要的映射文件,比如redis.conf,还有sentinel.conf等,如下为一个sentinel.conf的实例:
1 2 3 4
| port 26379 sentinel monitor mymaster 192.168.186.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000
|
指定 Sentinel 监听的端口为 26379。这个端口用于接收来自客户端和其他 Redis 实例的请求。
sentinel monitor mymaster:定义了一个监控的主节点,命名为 mymaster。
192.168.186.1:这是主节点的 IP 地址(可以是服务名,如果在 Docker 中使用)。
6379:主节点的端口。
2:表示需要在多数 Sentinel 同意的情况下,认为主节点是故障的,即至少需要 2 个 Sentinel 实例认为主节点故障才能触发故障转移。
sentinel down-after-milliseconds mymaster 5000设置一个超时阈值,当主节点在 5000 毫秒(5 秒)内未响应时,Sentinel 会将其标记为“下线”(即故障)。这意味着在此时间内,如果没有收到主节点的心跳,Sentinel 会认为主节点可能故障。
sentinel failover-timeout mymaster 60000设置故障转移的超时值为 60000 毫秒(60 秒)。当主节点被标记为故障后,Sentinel 会在这个时间内尝试执行故障转移操作。如果在这段时间内故障转移成功,Sentinel 会将新的主节点推向集群。
而后,创建一个yml文件,采用docker-compose的方式进行部署,可以参考https://github.com/gagaducko/learning_demos/tree/main/redis-sentinel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| version: '3.8'
networks: redis-net: driver: bridge
services: redis-master: image: redis:bullseye ports: - "6379:6379" command: ["redis-server", "--protected-mode no"] networks: - redis-net redis-slave1: image: redis:bullseye ports: - "6380:6379" command: ["redis-server", "--protected-mode no", "--slaveof", "redis-master", "6379"] networks: - redis-net
redis-slave2: image: redis:bullseye ports: - "6381:6379" command: ["redis-server", "--protected-mode no", "--slaveof", "redis-master", "6379"] networks: - redis-net
sentinel1: image: redis:bullseye ports: - "26379:26379" command: ["redis-sentinel", "/etc/redis/sentinel.conf"] volumes: - ./redis-sentinel1-conf:/etc/redis networks: - redis-net
sentinel2: image: redis:bullseye ports: - "26380:26379" command: ["redis-sentinel", "/etc/redis/sentinel.conf"] volumes: - ./redis-sentinel2-conf:/etc/redis networks: - redis-net
sentinel3: image: redis:bullseye ports: - "26381:26379" command: ["redis-sentinel", "/etc/redis/sentinel.conf"] volumes: - ./redis-sentinel3-conf:/etc/redis networks: - redis-net
|
运行该yml:
显示如下:
1 2 3 4 5 6 7 8
| [+] Running 7/7 ✔ Network redis-sentinel_redis-net Created 0.0s ✔ Container redis-sentinel-redis-slave1-1 Started 1.2s ✔ Container redis-sentinel-redis-slave2-1 Started 0.9s ✔ Container redis-sentinel-sentinel3-1 Started 1.4s ✔ Container redis-sentinel-sentinel1-1 Started 1.7s ✔ Container redis-sentinel-redis-master-1 Started 1.7s ✔ Container redis-sentinel-sentinel2-1 Started 1.5s
|
docker的显示如下:

sentinel1的logs如下:
1 2 3 4 5 6 7 8 9 10 11 12
| 1:X 02 Oct 2024 08:51:43.248 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 1:X 02 Oct 2024 08:51:43.248 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started 1:X 02 Oct 2024 08:51:43.248 # Configuration loaded 1:X 02 Oct 2024 08:51:43.248 * monotonic clock: POSIX clock_gettime 1:X 02 Oct 2024 08:51:43.249 * Running mode=sentinel, port=26379. 1:X 02 Oct 2024 08:51:43.249 # Sentinel ID is b20b1bc8496a99c92c9ce678192d8137142c19e2 1:X 02 Oct 2024 08:51:43.249 # +monitor master mymaster 192.168.186.1 6379 quorum 2 1:X 02 Oct 2024 08:51:44.679 * +sentinel-address-switch master mymaster 192.168.186.1 6379 ip 172.25.0.2 port 26379 for 47cd49c23b5fdc0c43cec035689ba42fcae72dc8 1:X 02 Oct 2024 08:51:45.291 * +sentinel-invalid-addr sentinel a944f333ad8ed5484bbde9682d34b35218c500ef 172.25.0.6 26379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:51:45.292 * +sentinel sentinel b20b1bc8496a99c92c9ce678192d8137142c19e2 172.25.0.6 26379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:51:45.497 * +sentinel-address-switch master mymaster 192.168.186.1 6379 ip 172.25.0.7 port 26379 for a944f333ad8ed5484bbde9682d34b35218c500ef 1:X 02 Oct 2024 08:51:53.272 * +slave slave 172.25.0.4:6379 172.25.0.4 6379 @ mymaster 192.168.186.1 6379
|
同时,可以看到映射出来的sentinel.conf发生了变化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| port 26379 sentinel monitor mymaster 192.168.186.1 6379 2 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 60000 # Generated by CONFIG REWRITE user default on nopass sanitize-payload ~* &* +@all dir "/data" sentinel myid b20b1bc8496a99c92c9ce678192d8137142c19e2 sentinel config-epoch mymaster 0 sentinel leader-epoch mymaster 0 sentinel current-epoch 0 sentinel known-replica mymaster 172.25.0.5 6379 sentinel known-sentinel mymaster 172.25.0.6 26379 b20b1bc8496a99c92c9ce678192d8137142c19e2 sentinel known-sentinel mymaster 172.25.0.2 26379 47cd49c23b5fdc0c43cec035689ba42fcae72dc8 sentinel known-sentinel mymaster 172.25.0.7 26379 a944f333ad8ed5484bbde9682d34b35218c500ef sentinel known-replica mymaster 172.25.0.4 6379
|
sentinel myid b20b1bc8496a99c92c9ce678192d8137142c19e。每个 Sentinel 实例都有一个唯一的 ID,这行指定了当前 Sentinel 的唯一标识符,用于识别和协调。
sentinel config-epoch mymaster 0。这表示监控的主节点(mymaster)的配置纪元,初始值为 0,通常在 Sentinel 进行配置更改时更新。
sentinel leader-epoch mymaster 0。表示当前领导者的纪元,初始为 0。这个值在发生故障转移时更新。
sentinel current-epoch 0。这是当前的纪元计数器,随着时间推移而更新,用于管理故障转移和配置版本。
sentinel known-replica mymaster 172.25.0.1 6379。这行记录了已知的从节点(replica),显示了它们的 IP 地址和端口。有三个从节点,分别是 172.25.0.1、172.25.0.2 和 172.25.0.3,这说明 Sentinel 能够识别并跟踪这些从节点。
sentinel known-sentinel mymaster 172.25.0.6 26379 b20b1bc8496a99c92c9ce678192d8137142c19e。记录已知的 Sentinel 实例,包括其 IP、端口和 ID。这里显示了 172.25.0.6 的 Sentinel 实例。
于此,一个简单的一主二从三哨兵的redis集群就完成了。
接下来,做一下简单的验证。
首先,先通过redis-cli连接到任一sentinel实例。这里选择一个sentinel的端口,比如26379:
1
| docker exec -it <sentinel1_container_id> redis-cli -p 26379
|
在 Sentinel CLI 中,运行以下命令查看主节点的状态:
这会列出所有被 Sentinel 监控的主节点及其状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 127.0.0.1:26379> SENTINEL masters 1) 1) "name" 2) "mymaster" 3) "ip" 4) "172.25.0.4" 5) "port" 6) "6379" 7) "runid" 8) "888febfd6c393ff1f1a8b34a6b80da70336674e5" 9) "flags" 10) "master" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "740" 19) "last-ping-reply" 20) "740" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "9744" 25) "role-reported" 26) "master" 27) "role-reported-time" 28) "254766" 29) "config-epoch" 30) "1" 31) "num-slaves" 32) "4" 33) "num-other-sentinels" 34) "3" 35) "quorum" 36) "2" 37) "failover-timeout" 38) "60000" 39) "parallel-syncs" 40) "1"
|
同样,可以查看从节点的状态:
1
| SENTINEL slaves mymaster
|
确保从节点是正确跟随主节点的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
| 127.0.0.1:26379> SENTINEL slaves mymaster 1) 1) "name" 2) "172.25.0.3:6379" 3) "ip" 4) "172.25.0.3" 5) "port" 6) "6379" 7) "runid" 8) "896cae5dbdc2e4996105636a182710d4112a1d26" 9) "flags" 10) "slave" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "801" 19) "last-ping-reply" 20) "801" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "2402" 25) "role-reported" 26) "slave" 27) "role-reported-time" 28) "323732" 29) "master-link-down-time" 30) "0" 31) "master-link-status" 32) "ok" 33) "master-host" 34) "172.25.0.4" 35) "master-port" 36) "6379" 37) "slave-priority" 38) "100" 39) "slave-repl-offset" 40) "83895" 41) "replica-announced" 42) "1" 2) 1) "name" 2) "172.25.0.5:6379" 3) "ip" 4) "172.25.0.5" 5) "port" 6) "6379" 7) "runid" 8) "a2d594cc616ed8f9530e7c1e2f0858e79187ba0f" 9) "flags" 10) "slave" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "315" 19) "last-ping-reply" 20) "315" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "6678" 25) "role-reported" 26) "slave" 27) "role-reported-time" 28) "327733" 29) "master-link-down-time" 30) "0" 31) "master-link-status" 32) "ok" 33) "master-host" 34) "172.25.0.4" 35) "master-port" 36) "6379" 37) "slave-priority" 38) "100" 39) "slave-repl-offset" 40) "82815" 41) "replica-announced" 42) "1" 3) 1) "name" 2) "192.168.186.1:6379" 3) "ip" 4) "192.168.186.1" 5) "port" 6) "6379" 7) "runid" 8) "896cae5dbdc2e4996105636a182710d4112a1d26" 9) "flags" 10) "slave" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "709" 19) "last-ping-reply" 20) "709" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "6515" 25) "role-reported" 26) "slave" 27) "role-reported-time" 28) "327732" 29) "master-link-down-time" 30) "0" 31) "master-link-status" 32) "ok" 33) "master-host" 34) "172.25.0.4" 35) "master-port" 36) "6379" 37) "slave-priority" 38) "100" 39) "slave-repl-offset" 40) "83085" 41) "replica-announced" 42) "1" 4) 1) "name" 2) "172.25.0.1:6379" 3) "ip" 4) "172.25.0.1" 5) "port" 6) "6379" 7) "runid" 8) "896cae5dbdc2e4996105636a182710d4112a1d26" 9) "flags" 10) "slave" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "315" 19) "last-ping-reply" 20) "315" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "6678" 25) "role-reported" 26) "slave" 27) "role-reported-time" 28) "327733" 29) "master-link-down-time" 30) "0" 31) "master-link-status" 32) "ok" 33) "master-host" 34) "172.25.0.4" 35) "master-port" 36) "6379" 37) "slave-priority" 38) "100" 39) "slave-repl-offset" 40) "82815" 41) "replica-announced" 42) "1"
|
为了测试 Sentinel 的故障转移能力,可以手动停止主节点,观察 Sentinel 如何处理:
1
| docker stop <redis-master_container_id>
|
然后,等待几秒钟,使用以下命令再次连接 Sentinel,检查是否进行了故障转移:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| 127.0.0.1:26379> SENTINEL masters 1) 1) "name" 2) "mymaster" 3) "ip" 4) "172.25.0.4" 5) "port" 6) "6379" 7) "runid" 8) "888febfd6c393ff1f1a8b34a6b80da70336674e5" 9) "flags" 10) "master" 11) "link-pending-commands" 12) "0" 13) "link-refcount" 14) "1" 15) "last-ping-sent" 16) "0" 17) "last-ok-ping-reply" 18) "271" 19) "last-ping-reply" 20) "271" 21) "down-after-milliseconds" 22) "5000" 23) "info-refresh" 24) "181" 25) "role-reported" 26) "master" 27) "role-reported-time" 28) "435985" 29) "config-epoch" 30) "1" 31) "num-slaves" 32) "4" 33) "num-other-sentinels" 34) "3" 35) "quorum" 36) "2" 37) "failover-timeout" 38) "60000" 39) "parallel-syncs" 40) "1"
|
还可以查看sentinel容器的日志:
1
| docker logs <sentinel1_container_id>
|
看具体的一个内部状态和故障处理过程。
比如,sentinel1的日志:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| 1:X 02 Oct 2024 08:53:28.762 # +sdown master mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:28.825 # +odown master mymaster 192.168.186.1 6379 #quorum 2/2 1:X 02 Oct 2024 08:53:28.825 # +new-epoch 1 1:X 02 Oct 2024 08:53:28.825 # +try-failover master mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:28.853 # +vote-for-leader b20b1bc8496a99c92c9ce678192d8137142c19e2 1 1:X 02 Oct 2024 08:53:28.853 # b20b1bc8496a99c92c9ce678192d8137142c19e2 voted for b20b1bc8496a99c92c9ce678192d8137142c19e2 1 1:X 02 Oct 2024 08:53:28.885 # a944f333ad8ed5484bbde9682d34b35218c500ef voted for b20b1bc8496a99c92c9ce678192d8137142c19e2 1 1:X 02 Oct 2024 08:53:28.885 # 47cd49c23b5fdc0c43cec035689ba42fcae72dc8 voted for b20b1bc8496a99c92c9ce678192d8137142c19e2 1 1:X 02 Oct 2024 08:53:28.912 # +elected-leader master mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:28.912 # +failover-state-select-slave master mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:28.965 # +selected-slave slave 172.25.0.4:6379 172.25.0.4 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:28.965 * +failover-state-send-slaveof-noone slave 172.25.0.4:6379 172.25.0.4 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.048 * +failover-state-wait-promotion slave 172.25.0.4:6379 172.25.0.4 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.297 # +promoted-slave slave 172.25.0.4:6379 172.25.0.4 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.297 # +failover-state-reconf-slaves master mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.346 * +slave-reconf-sent slave 172.25.0.5:6379 172.25.0.5 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.402 * +slave-reconf-inprog slave 172.25.0.5:6379 172.25.0.5 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.402 * +slave-reconf-done slave 172.25.0.5:6379 172.25.0.5 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.458 * +slave-reconf-sent slave 172.25.0.1:6379 172.25.0.1 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.713 * +slave-reconf-inprog slave 172.25.0.1:6379 172.25.0.1 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.713 * +slave-reconf-done slave 172.25.0.1:6379 172.25.0.1 6379 @ mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.813 # +failover-end master mymaster 192.168.186.1 6379 1:X 02 Oct 2024 08:53:29.813 # +switch-master mymaster 192.168.186.1 6379 172.25.0.4 6379 1:X 02 Oct 2024 08:53:29.813 * +slave slave 172.25.0.5:6379 172.25.0.5 6379 @ mymaster 172.25.0.4 6379 1:X 02 Oct 2024 08:53:29.813 * +slave slave 172.25.0.1:6379 172.25.0.1 6379 @ mymaster 172.25.0.4 6379 1:X 02 Oct 2024 08:53:29.814 * +slave slave 192.168.186.1:6379 192.168.186.1 6379 @ mymaster 172.25.0.4 6379 1:X 02 Oct 2024 08:53:33.814 * +slave slave 172.25.0.3:6379 172.25.0.3 6379 @ mymaster 172.25.0.4 6379 1:X 02 Oct 2024 09:00:33.338 # +sdown slave 172.25.0.3:6379 172.25.0.3 6379 @ mymaster 172.25.0.4 6379 1:X 02 Oct 2024 09:00:33.338 # +sdown slave 192.168.186.1:6379 192.168.186.1 6379 @ mymaster 172.25.0.4 6379 1:X 02 Oct 2024 09:00:33.338 # +sdown slave 172.25.0.1:6379 172.25.0.1 6379 @ mymaster 172.25.0.4 6379
|
+sdown master mymaster 192.168.186.1 6379 表示 Sentinel 认为主节点不可用。
+odown master mymaster 192.168.186.1 6379 #quorum 2/2 表示故障达到了被确认的sentinel的数量被确认,需要进行故障转移。
+new-epoch 1 和 +try-failover master mymaster 表示开始进行故障转移。
+elected-leader master mymaster 表示选举出一个领导者进行故障转移。
+promoted-slave slave 172.25.0.4:6379 表示选定的从节点 172.25.0.4 被提升为新的主节点。
日志中有多个 +slave-reconf 记录,显示从节点被重新配置为跟随新主节点。
+failover-end master mymaster 192.168.186.1 6379 和 +switch-master mymaster 192.168.186.1 6379 172.25.0.4 6379 表示故障转移完成,新的主节点已被选定,并且从节点已被重新配置为跟随新的主节点。
最后几行显示从节点 172.25.0.3 和其他从节点(如 192.168.186.1)被标记为 sdown,表示它们在新的主节点下仍然不可用。
同时,也可以看见,在原先的slave1(172.25.0.4)中,以及变成了一个master节点,向slave1中,set key1 111后,可以set成功,并且在slave2中可以通过get key1得到111。
在这种情况下,即便重启了原先的redis-master,发现原先的master节点也变成了slave节点。
还可进一步的进行测试,把slave1关掉,发现,现在在slave2变成了一个可以set key的主节点而master变成了可以被slave2所同步的从节点,重新打开slave1后,slave1作为一个slave2的新的从节点加入到了这个集群中。