深入理解Redis Cluster(3)

Redis集群支持在线迁移slot和数据来完成水平伸缩,当slot对应的数据从源节点到目标节点迁移过程中,客户端需要做到智能识别,保证键命令可正常执行。例如,当一个slot数据从源节点迁移到目标节点时,可能会出现一部分数据在源节点,另一部分在目标节点。

如果出现这种情况,客户端键执行流程将发生变化,如下所示,

1. 客户端根据slot缓存发送命令到源节点,如果存在key则直接执行并返回结果。

2. 如果key不存在,则可能存在于目标节点,这时会回复ASK重定向异常,格式如下:(error) ASK {slot} {targetIP}:{targetPort}。

3. 客户单从ASK重定向异常提出目标节点信息,发送asking命令到目标节点打开客户端连接标识,再执行键命令。如果存在则执行,不存在则返回不存在信息。

ASK与MOVED虽然都是对客户端进的重定向,但是有着本质区别,前者说明集群正在进行slot数据迁移,所以只是临时性的重定向,不会更新slot缓存,但是MOVED重定向说明键对应的槽已经明确指定到新的节点,会更新slot缓存。

模拟Redis Cluster FAILOVER的过程

模拟主节点故障,手动kill 6379节点。

1. 首先,该节点对应的从节点会有日志输出。

16387:S 15 Oct 10:34:30.149 # Connection with master lost.
16387:S 15 Oct 10:34:30.149 * Caching the disconnected master state.
16387:S 15 Oct 10:34:30.845 * Connecting to MASTER 127.0.0.1:6379
16387:S 15 Oct 10:34:30.845 * MASTER <-> SLAVE sync started
16387:S 15 Oct 10:34:30.845 # Error condition on socket for SYNC: Connection refused
...
16387:S 15 Oct 10:34:49.994 * MASTER <-> SLAVE sync started
16387:S 15 Oct 10:34:49.994 # Error condition on socket for SYNC: Connection refused
16387:S 15 Oct 10:34:50.898 * FAIL message received from bd341bb4c10e0dbff593bf7bafb1309842fba155 about 72af03587f5e9f064721d3b3a92b1439b3785623
16387:S 15 Oct 10:34:50.898 # Cluster state changed: fail

发现连接断开的时间点是10:34:30.149,判断其主观下线的时间为10:34:50,相差20s,这也是cluster-node-timeout的设置。

2. 再来看看6380节点的日志。

16383:M 15 Oct 10:34:50.897 * Marking node 72af03587f5e9f064721d3b3a92b1439b3785623 as failing (quorum reached).
16383:M 15 Oct 10:34:50.897 # Cluster state changed: fail

6381节点的日志同样如此,超过半数,因此标记6379节点为客观下线。

3. 再来看看从节点的日志

16387:S 15 Oct 10:34:51.003 * Connecting to MASTER 127.0.0.1:6379
16387:S 15 Oct 10:34:51.003 * MASTER <-> SLAVE sync started
16387:S 15 Oct 10:34:51.003 # Start of election delayed for 566 milliseconds (rank #0, offset 154).
16387:S 15 Oct 10:34:51.003 # Error condition on socket for SYNC: Connection refused

从节点识别正在复制的主节点进入客观下线后准备选举时间,日志打印了选举延迟566毫秒之后执行。

延迟选举时间到达后,从节点更新配置纪元并发起故障选举。

16387:S 15 Oct 10:34:51.605 # Starting a failover election for epoch 7.

4. 6380和6381主节点为从节点投票

16385:M 15 Oct 10:34:51.618 # Failover auth granted to 886c1f990191854df1972c4bc4d928e44bd36937 for epoch 7

5. 从节点获取2个主节点投票之后,超过半数执行替换主节点操作,完成故障切换。

16387:S 15 Oct 10:34:51.622 # Failover election won: I'm the new master.
16387:S 15 Oct 10:34:51.622 # configEpoch set to 7 after successful failover
16387:M 15 Oct 10:34:51.622 # Setting secondary replication ID to 207c65316707a8ec2ca83725ae53ab49fa25dbfb, valid up to offset: 155. New replication ID is 0ec4aac9562b3f4165244153646d9c9006953736
16387:M 15 Oct 10:34:51.622 * Discarding previously cached master state.
16387:M 15 Oct 10:34:51.622 # Cluster state changed: ok

Failover的流程

一、主观下线

集群中每个节点都会定期向其他节点发送ping消息,接收节点回复pong消息作为响应。如果在cluster-node-timeout时间内通信一直失败,则发送节点会认为接收节点存在故障,把接收节点标记为主观下线(pfail)状态。


二、客观下线

当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播。通过Gossip消息传播,集群内节点不断收集到故障节点的下线报告。当半数以上持有槽的主节点都标记某个节点是主观下线时,触发客观下线流程。

集群中的节点每次接收到其他节点的pfail状态,都会尝试触发客观下线,流程说明:

1. 首先统计有效的下线报告数量,如果小于集群内持有槽的主节点总数的一半则退出。

2. 当下线报告大于槽主节点数量一半时,标记对应故障节点为客观下线状态。

3. 向集群广播一条fail消息,通知所有的节点将故障节点标记为客观下线,fail消息的消息体只包含故障节点的ID。

广播fail消息是客观下线的最后一步,它承担着非常重要的职责:

1. 通知集群内所有的节点标记故障节点为客观下线状态并立刻生效。

2. 通知故障节点的从节点触发故障转移流程。

三、故障切换

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/175512e5abc98ac31b76089c5f089927.html