社区版redis cluster是无中心节点P2P的集群架构,内部采用gossip协议传递维护集群的拓扑结构和集群元数据。社区文档地址:
https://redis.io/topics/cluster-tutorial
failover是redis cluster提供的容错机制,cluster最核心的功能之一。failover支持两种模式:
-
故障failover:自动恢复集群的可用性
-
人为failover:支持集群的可运维操作
1、故障failover
故障failover表现在一个master分片故障后,slave接管master的过程。
1.1、探测阶段
集群中的所有分片通过gossip协议传递。探测步骤为:
(1)在cron中非遍历cluster nodes做ping发送,随机从5个节点中选出最老pong_recv的节点发送ping,再遍历节点中pong_recv > timeout/2的节点发送ping。
(2)再遍历每个节点从发出ping包后超时没有收到pong包的时间,超时将对应的分片设置为pfail状态,在跟其他节点的gossip包过程中,每个节点会带上被标记为pfail状态的包。
(3)每个正常分片收到ping包后,统计集群中maste分片将故障节点设置为pfail, 超过一半以上的节点设置为pfail, 则将节点设置为fail状态。如果这个分片属于故障节点的slave节点,则主动广播故障节点为fail状态。
下图以3个节点集群来说明核心的流程:
1.2、准备阶段
在cron函数中,slave节点获取到master节点状态为fail,主动发起一次failover操作,该操作并不是立即执行,而是设计了多个限制:
(1)过期的超时不执行。如何判断是够过期? data_age = 当前时间点-上次master失联的时间点-超时时间
如果data_age > master到slave的ping间隔时间+超时时间*cluster_slave_validity_factor, 则认为过期。cluster_slave_validity_factor是一个配置项,cluster_slave_validity_factor 设置的越小越不容易触发failover。
(2)计算出一个延迟执行的时间failover_auth_time, failover_auth_time = 当前时间 + 500ms + 0-500ms的随机值 + 当前slave的rank*1s, rank按已同步的offset计算,offset同步的越延迟,rank值越大,该slave 就越推迟触发failover的时间,以此来避免多个slave同时failover。只有当前时间到failover_auth_time的时间点才会执行failover。
1.3、执行阶段
(1)将currentEpoch自增,再赋值给failover_auth_epoch
(2)向其他master分片发起failover投票,等待投票结果
(3)其他master分片收到CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST请求后,会判断是否符合以下情况:
-
epoch必须>=所有集群视图的master节点的epoch
-
发起者是slave
-
slave的master已是fail状态
-
在相同epoch内只投票一次
-
在超时时间(cluster_node_timeout)* 2的时间内只投票一次
(4)其他master回复CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK,slave端收到后做统计
(5)在cron中判断统计超过一半以上master回复,开始执行failover
(6)标记自身节点为master
(7)清理复制链路
(8)重置集群拓扑结构信息
(9)向集群内所有节点广播
下图以3个节点集群来说明核心的流程:
2、人为failover
人为failover支持三种模式的failover:缺省、force、takeover。
2.1、缺省
(1)给master 发送CLUSTERMSG_TYPE_MFSTART
(2)master收到后设置clients_pause_end_time = 当前时间+ 5s*2,clients_paused =1 ,客户端暂停所有请求,新建请求会被加到block client list。
(3)master在ping包中带上repl_offset的信息
(4)slave检查master的repl_offset,确认同步已完成
(5)设置mf_can_start = 1,在cron中开始正常的failover流程,不需要像故障failover设置推迟执行而是立即执行操作, 而且其他master投票时不需要考虑master是否为fail状态。
2.2、force
忽略主备同步的状态,设置mf_can_start = 1,标记failover开始。
2.3、takeover
直接执行故障failover的第6-9步,忽略主备同步,忽略集群其他master的投票。
3、结束语
云数据库Redis版(ApsaraDB for Redis)是一种稳定可靠、性能卓越、可弹性伸缩的数据库服务。基于飞天分布式系统和全SSD盘高性能存储,支持主备版和集群版两套高可用架构。提供了全套的容灾切换、故障迁移、在线扩容、性能优化的数据库解决方案。欢迎各位购买使用:
云数据库 Redis 版