导航:首页 > 配服务器 > redis哨兵如何确定主服务器

redis哨兵如何确定主服务器

发布时间:2023-05-06 00:17:00

A. Redis哨兵机制原理浅析

上一篇文章Redis主从复制原理中简要地说明了主从复制的一个基本原理,包含全量复制、复制积压缓冲区与增量复制等内容,有兴趣的同学可以先看下。

利用主从复制,可以实现读写分离、数据备份等功能。但如果主库宕机后,需要运维人员手动地将一个从库提升为新主库,并将其他从库slaveof新主库,以此来实现故障恢复。

因此, 主从模式的一个缺点,就在于无法实现自动化地故障恢复 。Redis后来引入了哨兵机制,哨兵机制大大提升了系统的高可用性。

哨兵,就是站岗放哨的,时刻监控周围的一举一动,在第一时间发现敌情并发出及时的警报。

Redis中的哨兵(Sentinel), 则是一个特殊的Redis实例 ,不过它并不存储数据。也就是说,哨兵在启动时,不会去加载RDB文件。

关于Redis的持久化,可以参考我的另外一篇文章 谈谈Redis的持久化——AOF日志与RDB快照

上图就是一个典型的哨兵架构,由数据节点与哨兵节点构成,通常会部署多个哨兵节点。

哨兵主要具有三个作用, 监控、选主与通知

监控:哨兵会利用心跳机制,周期性不断地检测主库与从库的存活性

选主:哨兵检测到主库宕机后,选择一个从库将之切换为新主库

通知:哨兵会将新主库的地址通知到所有从库,使得所有从库与旧主库slaveof新主库,也会将新主库的地址通知到客户端上

我会在下文详细讲一下监控与选主的过程

哨兵系统是通过3个定时任务,来完成对主库、从库与哨兵之间的探活。

首先我们会在配置文件中配置主库地址,这样哨兵在启动后,会以 每隔10秒 的频率向主库发送info命令,从而获得当前的主从拓扑关系,这样就拿到了所有从库的地址。

接着 每隔2秒 ,会使用pub/sub(发布订阅)机制,在主库上的 sentinel :hello的频道上发布消息,消息内容包括哨兵自己的ip、port、runid与主库的配置。

每个哨兵都会订阅该频道,在该频道上发布与消费消息,从而实现哨兵之间的互相感知。

利用启动配置与info命令可以获取到主从库地址,利用发布订阅可以感知到其余的哨兵节点。

在此基础上,哨兵会 每隔1秒 向主库、从库与其他哨兵节点发送PING命令,因此来进行互相探活。

当某个哨兵在 **down-after-milliseconds(默认是30秒) **配置的连续时间内,仍然没有收到主库的正确响应,则当前哨兵会认为主库 主观下线 ,并将其标记为sdown(subjective down)

为了避免当前哨兵对主库的误判,因此这个时候还需要参考其他哨兵的意见。

接着当前哨兵会向其他哨兵发送 sentinel is-master-down-by-addr 命令, 如果有半数以上(由quorum参数决定)的哨兵认为主库确实处于主观下线状态,则当前哨兵认为主库客观下线 ,标记为odown(objective down)

一旦某个主库被认定为客观下线时,这个时候需要进行哨兵选举,选举出一个领导者哨兵,来完成主从切换的过程。

哨兵A在向其他哨兵发送 sentinel is-master-down-by-addr 命令时,同时要求其他哨兵同意将其设置为Leader,也就是想获得其他哨兵的投票。

在每一轮选举中,每个哨兵仅有一票。投票遵循先来先到的原则,如果某个哨兵没有投给别人,就会投给哨兵A。

首先获得半数以上投票的哨兵,将被选举称为Leader。

这里的哨兵选举,采用的是Raft算法。这里不对Raft做详细的探讨,有兴趣的同学,可以参考我的另外一篇文章 22张图,带你入门分布式一致性算法Raft

该文章采用大量的图例,相信你可以从中学习到全新的知识,从而打开分布式一致性算法的大门,大伙们记得等我搞完Paxos与Zab。

过半投票机制也常用于很多算法中,例如RedLock,在半数以上的节点上加锁成功,才代表申请到了分布式锁,具体可参考这篇文章的最后 我用了上万字,走了一遍Redis实现分布式锁的坎坷之路,从单机到主从再到多实例,原来会发生这么多的问题

在Zookeeper选举中,同样也用到了过半投票机制,在这篇文章中 面试官:能给我画个Zookeeper选举的图吗? 我从源码角度分析了Zookeeper选举的过程。

在选举到领导者哨兵后,将由该哨兵完成故障恢复工作。

故障恢复分为以下两步:

详细说一下第一步,挑选是有条件的。首先要过滤出不健康的节点,再按某种规则排序,最后取第一个从库,我们直接从源码入手:

因此,以下从库会被过滤出:

剩下的节点,就是健康的节点,此时再执行一次快速排序,排序的规则如下:

本文算是Redis哨兵的一个入门文章,主要讲了哨兵的作用,例如监控、选主和通知。

在Redis读写分离的情况下,使用哨兵可以很轻松地做到故障恢复,提升了整体的可用性。

但哨兵无法解决Redis单机写的瓶颈,这就需要引入集群模式,相应的文章也被列为明年的写作计划中。

</article>

B. Redis(7):哨兵机制

        哨兵(sentinel),是redis集群架构中非常重要的一个组件,它主要的功能和特性如下:

(1)集群监控,负责监控redis master和slave进程是否正常工作。

(2)消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员。

(3)故障转移,如果master node挂掉了,会自动转移到slave node上。

(4)配置中心,如果故障转移发生了,通知client客户端新的master地址。

(5)哨兵本身也是分布式的,哨兵以集群的方式来相互协作。

(6)要进行故障转移时会涉及到分布式选举,当大部分哨兵节点都同意时才能进行。

(7)当部分哨兵节点不能正常工作时,哨兵集群还是能够正常工作。

        说到这个特点,我们就要说到两个参数,第一个是quorum,quorum是我们可以给哨兵集群配置的一个参数,它的作用是:当master节点宕机的时候需要有至少quorum个哨兵节点认为mater宕机才能进行后续的操作,比如主备切换、故障转移,这个时候还需要一个参数majority来判断是否可以进行故障转移,需要有大多数哨兵节点正常工作来同同意这次故障转移,即正常工作的哨兵节点数要大于majority,majority有一个通用的规则:2个哨兵节点的majority为2,3个哨兵节点的majority为2,4个哨兵节点的majority为2,5个哨兵节点的majority为3,以此类推。如果一个master节点宕机了,同时他的哨兵进程同时挂掉了,那么现在正常运行的哨兵节点数目为1,即使你把quorum设置为1,满足了quorum的条件,但是是不能满足正常运行的哨兵节点大于majority,也就是2,所以是不能保证能够进行故障转移的。

       第一种情况: maser节点和slave节点之间的数据传输不是同步的,是异步的,当客户端往master中写数据的时,master异步的发送给slave节点,这当中会存在一定的延迟,当master节点挂掉的时候是不能保证这一小部分数据会及时的发送给slave节点。

        第二种情况:当master节点与slave节点间发生网络故障,导致无法与slave节点通讯,产生网络分区。这时,老的master节点并没有视为宕机,仍然在不停的写数据。此时这个slave节点如果被选举为新的master节点,这样就会发生“集群脑裂”,客户端程序还是会源源不断地将数据写入老的master节点,新的master节点却没有接收到新的数据,当网络恢复正常,老的master节点降为slave节点的时候,会立即执行全量的主从复制,那么故障之后的数据就会丢失。

        现在我们有一主两从的这样一个redis 集群,每个redis节点有一个哨兵,我们设置quorum为2,那么当master节点宕机的话,此时三个哨兵还剩下两个,剩下的两个slave节点一致认为master宕机,此时三个哨兵节点的majority为2,剩下还有2个正常运行的哨兵节点,那么就可以选举出新的master节点进行故障转移。

        异步复制数据丢失,集群脑裂数据丢失的问题我们可以通过设置两个参数来减少数据丢失:

         min-slaves-to-write 1

        min-slaves-max-lag 10

        上面两个参数表达的意思为:要求至少有1个slave,数据复制和同步的延迟不能超过10秒。也就是说,如果所有的slave节点都落后于master节点10秒钟的数据,那么master节点就不会再接受任何请求了。

(1)减少异步复制的数据丢失

        有了min-slaves-max-lag这个配置,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低的可控范围内,最多也就丢失10秒的数据。

(2)减少脑裂的数据丢失

        如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求。这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失。上面的配置就确保了,如果跟任何一个slave丢了连接,在10秒后发现没有slave给自己ack,那么就拒绝新的写请求。因此在脑裂场景下,最多就丢失10秒的数据。

(3)当master不接受请求之后该如何处理

        当master不接受写请求之后,我们需要给client做降级,让它直接把数据写到本地磁盘里,让client自己处理这些数据,做相应的降级和限流,减慢数据涌入的速度。或者将数据写入一个消息队列,每隔一段时间取一次,尝试将数据重新写入到redis中。

        什么是sdown,sdown又称为主观宕机,即一个哨兵觉得master节点宕机,这就是sdown。odown又称为客观宕机,即现在有quorum个哨兵都认为master宕机了。判断sdown的条件就是:一个哨兵ping一个master,超过了is-master-down-after-milliseconds参数指定的毫秒数之后,就主观认为master宕机。sdown转换到odown的条件就是:如果一个哨兵在指定时间内收到了超过quorum个哨兵的认为该master节点宕机的信息,就转换成了odown。

        哨兵互相之间的发现,是通过redis的pub/sub系统实现的,每个哨兵都会往__sentinel__:hello这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在。每隔两秒钟,每个哨兵都会往自己监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是自己的host、ip和runid还有对这个master的监控配置。每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在。每个哨兵还会跟其他哨兵交换对master的监控配置,互相进行监控配置的同步。

        哨兵会负责自动纠正slave的一些配置,比如slave如果要成为潜在的master候选人,哨兵会确保slave在复制现有master的数据; 如果slave连接到了一个错误的master上,比如故障转移之后,那么哨兵会确保它们连接到正确的master上。

        如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave,会考虑slave的一些信息:

a.跟master断开连接的时长

b.slave优先级

c.复制offset

d.run id

        如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍(加上master宕机的时长),那么slave就被认为不适合选举为master。计算公式为:(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state。接下来会对slave进行排序:

a.按照slave优先级进行排序,slave priority越低,优先级就越高

b.如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级就越高

c.如果上面两个条件都相同,那么选择一个run id比较小的那个slave

        每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个哨兵来做切换,这个哨兵还得得到majority哨兵的授权,才能正式执行切换。如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换,但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换。

        哨兵会对一套redis master+slave进行监控,有相应的监控的配置,执行切换的那个哨兵,会从要切换到的新master(salve->master)那里得到一个configuration epoch,这就是一个版本号,每次切换的version号都必须是唯一的。如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的版本号。

        哨兵完成切换之后,会在自己本地更新生成最新的master配置,然后同步给其他的哨兵,就是通过之前说的pub/sub消息机制。这里之前的版本号就很重要了,因为各种消息都是通过一个channel去发布和监听的,所以一个哨兵完成一次新的切换之后,新的master配置是跟着新的版本号,其他的哨兵都是根据版本号的大小来更新自己的master配置的。

C. redis主从和哨兵

主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性

a,配置主从复制方式一、新增redis6380.conf, 加入 slaveof 192.168.152.128 6379, 在6379启动完后再启6380,完成配置;
b,配置主从复制方式二、redis-server --slaveof 192.168.152.128 6379 临时生效

c,查看状态:info replication
d,断开主从复制:在slave节点,执行6380:>slaveof no one
e,断开后再变成主从复制:6380:> slaveof 192.168.152.128 6379
f,数据较重要的节点,主从复制时使用密码验证: requirepass
e, 从节点建议用只读模式slave-read-only=yes, 若从节点修改数据,主从数据不一致
h,传输延迟:主从一般部署在不同机器上,复制时存在网络延时问题,redis提供repl-disable-tcp-nodelay参数决定是否关闭TCP_NODELAY,默认为关闭
参数关闭时:无论大小都会及时发布到从节点,占带宽,适用于主从网络好的场景,
参数启用时:主节点合并所有数据成TCP包节省带宽,默认为40毫秒发一次,取决于内核,主从的同步延迟40毫秒,适用于网络环境复杂或带宽紧张,如跨机房

a)一主一从:用于主节点故障转移从节点,当主节点的“写”命令并发高且需要持久化,可以只在从节点开启AOF(主节点不需要),这样即保证了数据的安全性,也避免持久化对主节点的影响

b)一主多从:针对“读”较多的场景,“读”由多个从节点来分担,但节点越多,主节点同步到多节点的次数也越多,影响带宽,也加重主节点的稳定

c)树状主从:一主多从的缺点(主节点推送次数多压力大)可用些方案解决,主节点只推送一次数据到从节点B,再由从节点B推送到C,减轻主节点推送的压力。

redis 2.8版本以上使用psync命令完成同步,过程分“全量”与“部分”复制
全量复制:一般用于初次复制场景(第一次建立SLAVE后全量)
部分复制:网络出现问题,从节点再次连接主节点时,主节点补发缺少的数据,每次数据增量同步
心跳:主从有长连接心跳,主节点默认每10S向从节点发ping命令,repl-ping-slave-period控制发送频率

a)主从复制,若主节点出现问题,则不能提供服务,需要人工修改配置将从变主
b)主从复制主节点的写能力单机,能力有限
c)单机节点的存储能力也有限

a)主节点(master)故障,从节点slave-1端执行 slaveof no one后变成新主节点;
b)其它的节点成为新主节点的从节点,并从新节点复制数据;
c)需要人工干预,无法实现高可用。

1. 为什么要有哨兵机制?

原理:当主节点出现故障时,由Redis Sentinel自动完成故障发现和转移,并通知应用方,实现高可用性。

其实整个过程只需要一个哨兵节点来完成,首先使用Raft算法(选举算法)实现选举机制,选出一个哨兵节点来完成转移和通知

任务1:每个哨兵节点每10秒会向主节点和从节点发送info命令获取最拓扑结构图,哨兵配置时只要配置对主节点的监控即可,通过向主节点发送info,获取从节点的信息,并当有新的从节点加入时可以马上感知到

任务2:每个哨兵节点每隔2秒会向redis数据节点的指定频道上发送该哨兵节点对于主节点的判断以及当前哨兵节点的信息,同时每个哨兵节点也会订阅该频道,来了解其它哨兵节点的信息及对主节点的判断,其实就是通过消息publish和subscribe来完成的

任务3:每隔1秒每个哨兵会向主节点、从节点及其余哨兵节点发送一次ping命令做一次心跳检测,这个也是哨兵用来判断节点是否正常的重要依据

客观下线:当主观下线的节点是主节点时,此时该哨兵3节点会通过指令sentinel is-masterdown-by-addr寻求其它哨兵节点对主节点的判断,当超过quorum(选举)个数,此时哨兵节点则认为该主节点确实有问题,这样就客观下线了,大部分哨兵节点都同意下线操作,也就说是客观下线

a)每个在线的哨兵节点都可以成为领导者,当它确认(比如哨兵3)主节点下线时,会向其它哨兵发is-master-down-by-addr命令,征求判断并要求将自己设置为领导者,由领导者处理故障转移;
b)当其它哨兵收到此命令时,可以同意或者拒绝它成为领导者;
c)如果哨兵3发现自己在选举的票数大于等于num(sentinels)/2+1时,将成为领导者,如果没有超过,继续选举…………

a)由Sentinel节点定期监控发现主节点是否出现了故障

sentinel会向master发送心跳PING来确认master是否存活,如果master在“一定时间范围”内不回应PONG 或者是回复了一个错误消息,那么这个sentinel会主观地(单方面地)认为这个master已经不可用了

b) 当主节点出现故障,此时3个Sentinel节点共同选举了Sentinel3节点为领导,负载处理主节点的故障转移

c) 由Sentinel3领导者节点执行故障转移,过程和主从复制一样,但是自动执行

流程:

1. 将slave-1脱离原从节点,升级主节点,

d) 故障转移后的redis sentinel的拓扑结构图

a) 过滤掉不健康的(下线或断线),没有回复过哨兵ping响应的从节点

b) 选择salve-priority从节点优先级最高(redis.conf)的

c) 选择复制偏移量最大,指复制最完整的从节点

以3个Sentinel节点、2个从节点、1个主节点为例进行安装部署

1. 前提: 先搭好一主两从redis的主从复制,和之前的主从复制搭建一样,搭建方式如下:

A)主节点6379节点(/usr/local/bin/conf/redis6379.conf):

修改 requirepass 12345678,注释掉#bind 127.0.0.1

B) 从节点redis6380.conf和redis6381.conf: 配置都一样

修改 requirepass 12345678 ,注释掉#bind 127.0.0.1,

加上访问主节点的密码masterauth 12345678 ,加上slaveof 192.168.152.128 6379

2. redis sentinel哨兵机制核心配置 (也是3个节点):

将三个文件的端口改成: 26379 26380 26381

然后:sentinel monitor mymaster 192.168.152.128 6379 2 //监听主节点6379

三个配置除端口外,其它一样。

3. 哨兵其它的配置 :只要修改每个sentinel.conf的这段配置即可:

sentinel monitor mymaster 192.168.152.128 6379 2

//监控主节点的IP地址端口,sentinel监控的master的名字叫做mymaster,2代表,当集群中有2个sentinel认为master死了时,才能真正认为该master已经不可用了

sentinel auth-pass mymaster 12345678 //sentinel连主节点的密码

sentinel config-epoch mymaster 2 //故障转移时最多可以有2从节点同时对新主节点进行数据同步

sentinel leader-epoch mymaster 2

sentinel failover-timeout mymasterA **180000 **//故障转移超时时间180s,

a,如果转移超时失败,下次转移时时间为之前的2倍;

b,从节点变主节点时,从节点执行slaveof no one命令一直失败的话,当时间超过 180S 时,则故障转移失败

c,从节点复制新主节点时间超过 180S 转移失败

sentinel down-after-milliseconds mymasterA 300000 //sentinel节点定期向主节点ping命令,当超过了 300S 时间后没有回复,可能就认定为此主节点出现故障了……

sentinel parallel-syncs mymasterA 1 //故障转移后, 1 代表每个从节点按顺序排队一个一个复制主节点数据,如果为3,指3个从节点同时并发复制主节点数据,不会影响阻塞,但存在网络和IO开销

4. 启动redis服务和sentinel服务:

a)先把之前安装的redis里面的标绿色的文件都拷贝到 usr/local/bin目录下,然后再再bin目录下新建一个conf文件夹存放配置好的redis主从配置文件和哨兵配置文件

b)启动主从复制服务,先启动主再启动从

主:./redis-server conf/redis6379.conf &

从:

./redis-server conf/redis6380.conf &

./redis-server conf/redis6381.conf &

c)启动sentinel服务:

./redis-sentinel conf/sentinel_26381.conf &

到此服务全部启动完毕

连接到6379的redis的服务,可看到6379就是主节点,他有6380和6381两个从节点

5. 测试: kill -9 6379 杀掉6379的redis服务

可以看到杀掉6379以后6380变为了主节点,6381变为了6380的从节点

重新启动6379以后变为6380的从节点

看日志是分配6380 是6381的主节点,当6379服务再启动时,已变成从节点

假设6380升级为主节点:进入6380>info replication 可以看到role:master

打开sentinel_26379.conf等三个配置,sentinel monitor mymaster 192.168.152.128 6380 2

打开redis6379.conf等三个配置, slaveof 192.168.152.128 6380,也变成了6380

注意:生产环境建议让redis Sentinel部署到不同的物理机上。

a,sentinel节点应部署在多台物理机(线上环境)

b,至少三个且奇数个sentinel节点

c,通过以上我们知道,3个sentinel可同时监控一个主节点或多个主节点

sentinel参考资料:
redis sentinel的机制与用法一: https://segmentfault.com/a/1190000002680804

redis sentinel的机制与用法二: https://segmentfault.com/a/1190000002685515

阅读全文

与redis哨兵如何确定主服务器相关的资料

热点内容
花书pdf 浏览:272
wps合成pdf文件 浏览:807
python教程pdf免费下载 浏览:959
程序员需求表 浏览:642
为什么安卓不能用qq登录 浏览:692
公开密钥加密哪年 浏览:831
程序员向 浏览:471
鼠标指针压缩包下载 浏览:764
登录认证失败请检查账号服务器地址 浏览:739
解压游戏覆盖方式 浏览:535
遗传算法的变异算子怎么实现 浏览:687
spring如何添加app 浏览:664
python循环import 浏览:552
怎样把js代码加密 浏览:800
frp服务器百度云 浏览:792
12306算法 浏览:630
单片机驱动小马达 浏览:100
pythoncookbook27 浏览:518
c的指针和python 浏览:186
python写sftp 浏览:958