一、哨兵机制相关基础知识介绍
1、哨兵简介
sentinal,中文名就是哨兵,哨兵是redis集群架构中的一个重要的组件,主要功能如下:
(1)、集群监控:负责监控redis master 和 slave 进程是否正常工作
(2)、消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员
(3)、故障转移:如果master node挂掉了,会自动转移到slave node上
(4)、配置中心:如果故障转移发生了,通知client客户端新的master地址
哨兵本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。故障转移时,判断一个master node是宕机了,需要大部分的哨兵同意才能进行,涉及到了分布式的选举问题。即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的,因为如果一个作为高可用机制重要组成部分的故障转移系统本身是单点的,那么一旦自身出问题了,就很难处理了。
目前采用的是sentinal 2版本, sentinal 2相对于sentinal 1来说,重写了很多代码,主要是让故障转移机制和算法变得更加健壮和简单。
2、哨兵知识的核心
(1)、哨兵至少需要3个实例,来保证自身的健壮性
(2)、哨兵 + redis 主从的部署架构,是不会保证数据零丢失的,只能保证redis集群的高可用性。
(3)、对于哨兵 + redis 主从这种复杂的架构部署,尽量在测试环境和生产环境都进行充足的测试和容灾演练
3、为什么redis哨兵集群只有2个节点后无法正常工作
哨兵集群必须部署2个以上的节点,如果哨兵仅仅部署了2个节点,此时,quorum = 1(配置文件中的配置)
如果master宕机,s1 和 s2中只要有1 个哨兵认为master宕机就可以进行切换,在s1 和 s2中会选举出一个哨兵来执行故障转移,同时,在这个时候,需要majority,也就是大多数哨兵都是运行的(2的majority=2,3的majority=2,5的majority=3,4的majority=2),如果2个哨兵都运行着,就可以进行故障转移,但是如果整个的M1和S1运行的机器宕机了,那么哨兵只有1个了,此时就没有majority来允许执行故障转移。
4、经典的3节点哨兵集群
如果M1所在机器宕机了,那么三个哨兵还剩下2个,S2和S3可以一致认为master宕机,然后选举出一个来执行故障转移,同时3个哨兵的majority是2,所以还剩下的2个哨兵运行着,就可以允许执行故障转移。
二、redis准备切换数据丢失问题:异步复制、集群脑裂
1、两种准备切换时导致数据丢失的情况
(1)、异步复制导致的数据丢失
因为master 到 slave 数据的复制过程是异步的,所以可能存在部分数据没有复制成功的时候,master宕机,而哨兵机制会将slave变为master,从而导致部分数据丢失。
(2)、脑裂导致的数据丢失
脑裂,也就是说某个master所在的机器突然脱离的正常的网络连接,跟其他slave机器不能连接,而实际上还是活着的,此时哨兵在slave机器上,因为无法和master进行连通,导致从新进行选举,指定其他的slave变为master。这时,集群中就会有两个master,这就是所谓的脑裂。
此时,虽然某一个slave被切换为了master,但是可能client还没有来得及切换到新的master上,还继续向原来的master中写数据,而旧的master通信恢复之后,可能会作为新的master的一个slave节点,需要同步新的master节点的数据,造成数据丢失。
2、解决异步复制和脑裂导致的数据丢失问题
redis的主配置文件中有如下配置:
min-slaves-to-write 1
min-slaves-max-lag 10
配置详解:要求至少有1个slave,数据复制和同步延迟的时间不能超过10秒。如果一旦所有的slave进行数据恢复和同步的延迟都超过了10秒,那么这个时候,master就不会再接受任何请求。
以上两行配置可以减少异步复制和脑裂导致的数据丢失。
(1)、减少异步复制的数据丢失
有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低的可控范围内
(2)、减少脑裂的数据丢失
如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求。这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失。
上面的配置就确保了,如果跟任何一个slave丢了连接,在10秒后发现没有slave给自己ack,那么就拒绝新的写请求,因此在脑裂场景下,最多就丢失10秒的数据
三、redis哨兵的4个核心底层原理(包含slave选举算法)
1、quorum和majority
(1)、quorum解释如下:
至少多少个哨兵要一致同意,master进程挂掉了,或者slave进程挂掉了,或者要启动一个故障转移操作。
quorum是用来识别故障的,真正执行故障转移的时候,还是要在哨兵集群执行选举,选举一个哨兵进程出来执行故障转移操作。
假设有5个哨兵,quorum设置了2,那么如果5个哨兵中的2个都认为master挂掉了; 2个哨兵中的一个就会做一个选举,选举一个哨兵出来,执行故障转移; 如果5个哨兵中有3个哨兵都是运行的,那么故障转移就会被允许执行。
(2)、majority
每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个哨兵来做切换,这个哨兵还得得到majority哨兵的授权,才能正式执行切换。
如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换。但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换。
2、sdown和odown转换机制
sdown和odown两种失败状态:
sdown:是主观宕机,就是一个哨兵如果自己觉得一个master宕机了,那么就是sdown(主观宕机)
odwon:是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那就是odown(客观宕机)
sdown达成的条件很简单,如果一个哨兵ping一个master,超过了is-master-down-after-milliseconds指定的毫秒数之后,就主观认为master宕机。
sdown到odown转换的条件很简单,如果一个哨兵在指定时间内,收到了quorum指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机。
3、哨兵集群的自动发现机制
哨兵互相之间的发现,是通过redis的pub / sub系统实现的,每个哨兵都会往__sentinel__:hello这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在。
每隔两秒钟,每个哨兵都会往自己监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是自己的host、ip和runid还有对这个master的监控配置。
每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在。
每个哨兵还会跟其他哨兵交换对master的监控配置,互相进行监控配置的同步。
4、slave配置的自动纠正
哨兵会负责自动纠正slave的一些配置,比如slave如果要成为潜在的master候选人,哨兵会确保slave在复制现有master的数据; 如果slave连接到了一个错误的master上,比如故障转移之后,那么哨兵会确保它们连接到正确的master上。
5、slave 和 master的选举算法
如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave来。
选举时会考虑slave的一些信息:
(1)跟master断开连接的时长
(2)slave优先级
(3)复制offset
(4)run id
如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master。
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对slave进行排序:
(1)按照slave优先级进行排序,slave priority越低,优先级就越高
(2)如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级就越高
(3)如果上面两个条件都相同,那么选择一个run id比较小的那个slave
6、configuration epoch
哨兵会对一套redis master+slave进行监控,有相应的监控的配置
执行切换的那个哨兵,会从要切换到的新master(salve->master)那里得到一个configuration epoch,这就是一个version号,每次切换的version号都必须是唯一的
如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的version号
7、configuration传播
哨兵完成切换之后,会在自己本地更新生成最新的master配置,然后同步给其他的哨兵,就是通过之前说的pub/sub消息机制。这里之前的version号就很重要了,因为各种消息都是通过一个channel去发布和监听的,所以一个哨兵完成一次新的切换之后,新的master配置是跟着新的version号的。其他的哨兵都是根据版本号的大小来更新自己的master配置的。
四、以经典的3节点方式部署哨兵集群
1、哨兵的配置文件讲解
redis根目录下有一个sentinel.conf配置文件为哨兵的默认配置文件。
# 指定对一个master节点的监控,mymaster:主机名 后面为:ip 端口号 2:代表quorum数量
sentinel monitor mymaster 127.0.0.1 6379 2
# 配置master上的redis登录密码
sentinel auth-pass mymaster master-redis-pass
# down-after-milliseconds,超过多少毫秒跟一个redis实例断了连接,哨兵就可能认为这个redis实例挂了
sentinel down-after-milliseconds mymaster 60000
# failover-timeout,执行故障转移的timeout超时时长
sentinel failover-timeout mymaster 180000
# parallel-syncs,新的master别切换之后,同时有多少个slave被切换到去连接新master(即同意时间每次进行挂接操作的slave数量)。重新做同步时,数字越低,花费的时间越多
sentinel parallel-syncs mymaster 1
# 以上配置代表一个master节点,一套sentinel架构可以监控多个主从架构,重复以上配置即可
sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
sentinel monitor mymaster 127.0.0.1 6379
以上是哨兵配置文件的最小配置,每一个哨兵可以去监控过个master-slaves的主从架构,在实际环境中,为了不同的项目部署了多个不同的master-slaves主从集群,可以使用相同的一套哨兵集群去监控不同的多个redis主从集群。
2、搭建哨兵集群准备工作(在cache-03机器上安装redis)
cache-03上搭建redis只需要安装就可以了,不需要进行部署redis实例的启动(配置生产环境)。因为cache-03只作为redis的哨兵服务器,不进行redis的启动。
tar -zxvf redis-3.2.8.tar.gz
cd redis-3.2.8
make && make install
3、配置哨兵集群
注意:哨兵默认端口号为26379,默认不能跟其他的机器的指定端口连通,只能连接本地。
(1)、cache-01上配置哨兵配置文件
在/etc下创建 sentinel 文件夹,拷贝redis根目录下的哨兵配置文件:sentinel.conf 到sentinel文件夹下并改名为5000.conf
在5000.conf中配置哨兵监控的具体信息
注意:如果master主机上的redis有密码的话,一定要在哨兵中配置连接密码
创建数据目录
(2)、cache-02 和 cache-03 机器上分别重复以上步骤
略。。。(绑定ip是绑定自己主机的ip)
4、启动哨兵进程
在cache-01、cache-02、cache-03三台机器上,分别启动三个哨兵进程,组成一个集群,观察一下日志的输出
5、连接哨兵
其他命令:
# 查看主节点信息
sentinel master mymaster
# 查看从节点信息
SENTINEL slaves mymaster
# 查看哨兵节点间关系信息
SENTINEL sentinels mymaster
# 查询主节点ip信息
SENTINEL get-master-addr-by-name mymaster
6、哨兵节点生产环境的配置:设置哨兵节点的后台启动以及日志信息的记录
创建哨兵日志文件夹:
每台哨兵机器上分别停止哨兵服务,删除配置文件中的masterid,加入后台启动配置以及日志信息记录配置:
重启哨兵,查看日志信息
五、哨兵架构的管理
1、哨兵节点的增加和删除
(1)、添加哨兵节点
参考部署哨兵节点,部署完成之后,其他哨兵节点会自动发现新添加的哨兵节点
(2)、删除哨兵节点
停止要删除的机器上的sentinel进程,在其他所有的sentinel机器上执行 SENTINEL RESET * 命令,清理所有的master状态,清理后,在所有的sentinel机器上执行 SENTINEL MASTER mastername 命令,查看所有的sentinel数量是否达成一致。
2、Slave节点的永久下架
slave节点下架之后,让master摘除已经下架的节点,需要在所有的sentinel机器上执行 SENTINEL RESET mastername 命令。
六、reids基于高可用集群架构的容灾演练(模拟master宕机后重连)
1、模拟master宕机
(1)、查看master主机上redis进程,并kill
(2)、观察三台主机上的sentinel日志信息
cache-01
cachae-02
cache-03
(3)、登录130节点的redis,查看从节点信息
结论:一定时间内,master主机被判定odown之后,sentinel会根据选举机制重新选举新的master(此次试验130节点被选中为master)
2、重新恢复cache-01主机上的redis服务并查看日志信息
(1)、恢复服务
(2)、日志信息
cache-01
cache-02
cache-03
(3)、查看master节点信息
(4)、测试数据复制
在master主机上(此时为130)添加一条数据,在128 slave node上可以查询到master添加的数据