rediscli 选择库 redis选举_rediscluster

Redis集群选举原理


开始之前,先说下这个参数

cluster-node-timeout

真实世界的机房网络往往并不是风平浪静的,它们经常会发生各种各样的小问题。比如网络抖动就是非常常见的一种现象,突然之间部分连接变得不可访问,然后很快又恢复正常。
为解决这种问题,Redis Cluster 提供了一种选项cluster-node-timeout,表示当某个节点持续 timeout 的时间失联时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频繁切换 (数据的重新复制)。

开始,先重现主从切换
先查看一下当前集群节点信息

[root@localhost redis-cluster]# /usr/local/redis/redis-5.0.2/src/redis-cli -c -h 192.168.5.100 -p 8001
192.168.5.100:8001> cluster nodes
412b26f846f27a63484594af931b9fb3b612ee9c 192.168.5.100:8003@18003 master - 0 1544973259457 3 connected 10923-16383
6c2000bf49a6e8229e518432c74d222521ff2f41 192.168.5.100:8005@18005 slave 1204327cbb9eaf4c9be0b90880531f6861e65f13 0 1544973258448 5 connected
52c723f6d391bc2975b27a5210451a2cf590d939 192.168.5.100:8002@18002 master - 0 1544973258000 2 connected 5461-10922
1d8f23d4ed7ccdfb5a6f2d8b9b6286cfd25d1d4b 192.168.5.100:8006@18006 slave 52c723f6d391bc2975b27a5210451a2cf590d939 0 1544973260466 6 connected
1204327cbb9eaf4c9be0b90880531f6861e65f13 192.168.5.100:8001@18001 myself,master - 0 1544973257000 1 connected 0-5460
886c96bfdef55b2fbcfee6eceb77fcf294fdfe33 192.168.5.100:8004@18004 slave 412b26f846f27a63484594af931b9fb3b612ee9c 0 1544973257440 4 connected
192.168.5.100:8001>

这时候我们kill掉一个master,再查看一下节点信息

[root@localhost redis-cluster]# /usr/local/redis/redis-5.0.2/src/redis-cli -c -h 192.168.5.100 -p 8002
192.168.5.100:8002> cluster nodes
6c2000bf49a6e8229e518432c74d222521ff2f41 192.168.5.100:8005@18005 slave 1204327cbb9eaf4c9be0b90880531f6861e65f13 0 1544973521650 5 connected
1d8f23d4ed7ccdfb5a6f2d8b9b6286cfd25d1d4b 192.168.5.100:8006@18006 slave 52c723f6d391bc2975b27a5210451a2cf590d939 0 1544973521000 6 connected
886c96bfdef55b2fbcfee6eceb77fcf294fdfe33 192.168.5.100:8004@18004 slave 412b26f846f27a63484594af931b9fb3b612ee9c 0 1544973522659 4 connected
412b26f846f27a63484594af931b9fb3b612ee9c 192.168.5.100:8003@18003 master - 0 1544973520000 3 connected 10923-16383
1204327cbb9eaf4c9be0b90880531f6861e65f13 192.168.5.100:8001@18001 master - 1544973509291 1544973508479 1 disconnected 0-5460
52c723f6d391bc2975b27a5210451a2cf590d939 192.168.5.100:8002@18002 myself,master - 0 1544973522000 2 connected 5461-10922
192.168.5.100:8002> cluster nodes
6c2000bf49a6e8229e518432c74d222521ff2f41 192.168.5.100:8005@18005 master - 0 1544973547997 7 connected 0-5460
1d8f23d4ed7ccdfb5a6f2d8b9b6286cfd25d1d4b 192.168.5.100:8006@18006 slave 52c723f6d391bc2975b27a5210451a2cf590d939 0 1544973549010 6 connected
886c96bfdef55b2fbcfee6eceb77fcf294fdfe33 192.168.5.100:8004@18004 slave 412b26f846f27a63484594af931b9fb3b612ee9c 0 1544973546000 4 connected
412b26f846f27a63484594af931b9fb3b612ee9c 192.168.5.100:8003@18003 master - 0 1544973543000 3 connected 10923-16383
1204327cbb9eaf4c9be0b90880531f6861e65f13 192.168.5.100:8001@18001 master,fail - 1544973509291 1544973508479 1 disconnected
52c723f6d391bc2975b27a5210451a2cf590d939 192.168.5.100:8002@18002 myself,master - 0 1544973548000 2 connected 5461-10922
192.168.5.100:8002>

我们看到这时候,8001显示的是fail,而8005则选举为master,这时候我们将8001重新启动,查看一下节点信息

192.168.5.100:8002> cluster nodes
6c2000bf49a6e8229e518432c74d222521ff2f41 192.168.5.100:8005@18005 master - 0 1544973819402 7 connected 0-5460
1d8f23d4ed7ccdfb5a6f2d8b9b6286cfd25d1d4b 192.168.5.100:8006@18006 slave 52c723f6d391bc2975b27a5210451a2cf590d939 0 1544973821440 6 connected
886c96bfdef55b2fbcfee6eceb77fcf294fdfe33 192.168.5.100:8004@18004 slave 412b26f846f27a63484594af931b9fb3b612ee9c 0 1544973822000 4 connected
412b26f846f27a63484594af931b9fb3b612ee9c 192.168.5.100:8003@18003 master - 0 1544973821000 3 connected 10923-16383
1204327cbb9eaf4c9be0b90880531f6861e65f13 192.168.5.100:8001@18001 slave 6c2000bf49a6e8229e518432c74d222521ff2f41 0 1544973822450 7 connected
52c723f6d391bc2975b27a5210451a2cf590d939 192.168.5.100:8002@18002 myself,master - 0 1544973821000 2 connected 5461-10922
192.168.5.100:8002>

这时候8001位slave,它的master:6c2000bf49a6e8229e518432c74d222521ff2f41,也就是8005,可见redis的高可用还是靠谱的。


原理分析:

当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有多个slave,从而存在多个slave竞争成为master节点的过程, 其过程如下:
1.slave发现自己的master变为FAIL
2.将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息
3.其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack
4.尝试failover的slave收集FAILOVER_AUTH_ACK
5.超过半数后变成新Master
6.广播Pong通知其他集群节点。

从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待FAIL状态在集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票

延迟计算公式:
DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms

SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)。


补充之前的一个问题:

跳转重定位

当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。客户端收到指令后除了跳转到正确的节点上去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽位映射表。

[root@localhost 8001]# /usr/local/redis/redis-5.0.2/src/redis-cli -c -h 192.168.5.100 -p 8003
192.168.5.100:8003> get name
-> Redirected to slot [5798] located at 192.168.5.100:8002
"xxx"
192.168.5.100:8002>

完。