Redis如何做到高可用
哨兵模式
Sentinel 是 Redis 的一种运行模式 ,它主要的作用就是对 Redis 运行节点进行监控。当 master 节点出现故障的时候, Sentinel 会帮助我们实现故障转移,确保整个 Redis 系统的可用性。整个过程完全自动,不需要人工介入。
- 集群监控:复制监控master与slave进程是否正常工作
- 消息通知:如果某个实例有古樟,那么哨兵负责发送消息作为报警通知给管理员
- 故障转移:master挂掉,会自动转移到slave
- 配置中心:如果故障转移发生,会通知客户端新的master地址
- 故障转移时,判断一个master是否宕机,需要大部分哨兵同意才行,涉及到分布式选举
- 及时部分哨兵节点故障,哨兵集群还能正常工作
哨兵核心知识
- 哨兵需要至少3个实例保证自己的健壮
- 哨兵+Redis主从的部署架构,不保证数据不丢失,只能保证Redis集群的高可用
哨兵主备切换的数据丢失问题
导致数据丢失的两种情况
主备切换的过程,可能会导致数据丢失
-
异步复制导致数据丢失 因为master到slave复制是异步的,所以可能有部分数据没有复制到slave,master就宕机了,此时部分数据就丢失。
-
脑裂导致数据丢失 就是在主从集群中,同时有两个主节点,它们都能够接收写请求。而脑裂最直接的影响就是客户端不知道应该往那个主节点写入数据,结果就是不同的客户端往不同的主节点写入数据,严重的话,脑裂会导致数据丢失。
数据丢失的解决方案
进行如下配置
min-slaves-to-write 1
min-slaves-max-lag 10
表示,要求至少有 1 个 slave,数据复制和同步的延迟不能超过 10 秒。
如果说一旦所有的 slave,数据复制和同步的延迟都超过了 10 秒钟,那么这个时候,master 就不会再接收任何请求了。
-
减少异步复制数据丢失 有了
min-slaves-max-lag
这个配置,可以确保一旦slave复制数据延时太长,就认为可能master宕机后损失数据太多,就拒绝写请求,可以把master宕机时由于部分数据没同步到slave导致数据的丢失降低在可控范围。 -
减少脑裂的数据丢失 如果一个master出现了脑裂,其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量slave发送数据,而且slave超过10s没有给自己消息,那么就直接拒绝客户端写请求。因此最多丢失10s的数据
sdown和odown转换机制
-
sdown是主观宕机,就一个哨兵如果觉得一个master宕机,就是主观宕机 sdown达成的条件很简单,如果一个哨兵ping一个master超过指定毫秒,就主观认为master宕机了
-
odown是客观宕机,如果半数以上的哨兵觉得一个master宕机,就是客观宕机 如果一个哨兵在指定时间内,收到了半数以上的其他哨兵也认为那个master宕机,那就是客观宕机
哨兵集群自动发现机制
哨兵之间的发现,是通过Redis的pub/sub系统实现的,每个哨兵都会往一个channel发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知其他哨兵的存在。
每隔2s,每个哨兵都会往自己监控的某个channel发送一个消息,内容是自己的host、ip和runid与对这个master的监控配置。
每个哨兵也会去监听自己的监控的每个master+slave对应的channel,然后去感知同样在监控这个channel其他哨兵的存在。
每个哨兵还会与其他哨兵交换对master的监控配置,互相进行监控配置同步。
slave配置的自动纠正
哨兵会负责启动纠正slave的一些配置,比如slave如果要成潜在的master候选人,哨兵会确保slave复制现有master的数据;如果slave连接一个错误的master上,比如故障转移之后,那么哨兵会确保他们连接到正确的master上。
slave->master选举算法
如果一个master被认为客观宕机,而且majority数量的哨兵都会允许主备切换,那么某个哨兵就会执行主备切换操作,此时先选举一个slave,会考虑slave一些信息:
- 跟master断开连接的时长
- slave优先级
- 复制offset
- run id 如果一个slave与master断开连接的时间超过了指定时间的10倍+master宕机事件,那么slave会被认为不适合选举为master
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对slave进行排序
- 按照slave优先级排序,slave priority越低,优先级越高
- 如果slave priority相同,那么看replica offset,哪个复制的数据越多,offset越后,优先级越高。
- 如果上面两个条件相同,那么选择run id比较小的那个slave
quorum和majority
每次一个哨兵要做主备切换,需要quorum数量的哨兵认为客观下线,然后选举一个哨兵来做切换,这个哨兵还要得到majority哨兵授权,才能正式执行切换。
如果quorum<majority,比如5个哨兵,majority就是3,quorum设置为2,那么3个哨兵授权就可以执行切换。
但是如果 quorum >= majority,那么必须 quorum 数量的哨兵都授权,比如 5 个哨兵,quorum 是 5,那么必须 5 个哨兵都同意授权,才能执行切换。
configuration epoch
哨兵会对一套 Redis master+slaves 进行监控,有相应的监控的配置。
执行切换的那个哨兵,会从要切换到的新 master(salve->master)那里得到一个 configuration epoch,这就是一个 version 号,每次切换的 version 号都必须是唯一的。
如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待 failover-timeout 时间,然后接替继续执行切换,此时会重新获取一个新的 configuration epoch,作为新的 version 号。
configuration 传播
哨兵完成切换之后,会在自己本地更新生成最新的 master 配置,然后同步给其他的哨兵,就是通过之前说的 pub/sub 消息机制。
这里之前的 version 号就很重要了,因为各种消息都是通过一个 channel 去发布和监听的,所以一个哨兵完成一次新的切换之后,新的 master 配置是跟着新的 version 号的。其他的哨兵都是根据版本号的大小来更新自己的 master 配置的。
Enjoy Reading This Article?
Here are some more articles you might like to read next: