sentinel 官方文档_redis哨兵(Sentinel)模式详解

官方文档

https://redis.io/topics/sentinel

简介

Redis Sentinel为Redis提供高可用性Sentinel模式是一种特殊的模式,首先Redis提供了Sentinel的命令,Sentinel是一个独立的进程,作为进程,它会独立运行其原理是Sentinel通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例

作用

  • 通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器
  • 通知Sentinel可以通过API通知系统管理员,另一台计算机程序,其中一个受监控的Redis实例出现问题
  • 当Sentinel监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机
  • Configuration provider客户端连接Sentinel可以获得当前Redis主服务器的地址等

结构图

c3882b60e88064d396f7202c1bf71e66.png

名词解释

  1. quorum:确认odown的最少的Sentinel数量
  2. majority:授权进行主从切换的最少的Sentinel数量
  3. failover:Sentinel确认odown进行故障转移的过程
  4. odown:多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover.
  5. sdown:当前 Sentinel 实例对某个redis服务器做出的下线判断

docker实例

拉取镜像docker pull redis

master配置 折叠原码# 指定日志文件logfile "redis.log"# 指定端口port 6380# 指定数据目录,rdb、aof文件也会写在这个目录dir /data# 以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的# AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式# 理解掌握好AOF持久化机制对兼顾数据安全性和性能非常有帮助通俗一点的理解就是以日志# 的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加# 文件但不可以改写文件,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作appendonly yes# 指定AOFappendfilename appendonly.aof# master设置的连接验证 从库要用masterauth来进行连接requirepass 1234# slave连接master验证 都加上此配置,当完成failover后仍然保持master需要验证masterauth 1234# slave1# 指定日志文件logfile "redis.log"# 指定端口port 6381# 指定数据目录,rdb、aof文件也会写在这个目录dir /data# 是否开启AOF模式appendonly yes# 指定AOFappendfilename appendonly.aof# 指定masterslaveof 172.16.81.232 6380# master设置的连接验证 从库要用masterauth来进行连接requirepass 1234# slave连接master验证 都加上此配置,当完成failover后仍然保持master需要验证masterauth 1234# slave2# 指定日志文件logfile "redis.log"# 指定端口port 6382# 指定数据目录,rdb、aof文件也会写在这个目录dir /data# 是否开启AOF模式appendonly yes# 指定AOFappendfilename appendonly.aof# 指定masterslaveof 172.16.81.232 6380# master设置的连接验证 从库要用masterauth来进行连接requirepass 1234# slave连接master验证 都加上此配置,当完成failover后仍然保持master需要验证masterauth 1234

启动容器docker run -it --name redis-master -p 6380:6380 -v /Users/zhudd/redisTest/6380/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.confdocker run -it --name redis-slave1 -p 6381:6381 -v /Users/zhudd/redisTest/6381/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.confdocker run -it --name redis-slave2 -p 6382:6382 -v /Users/zhudd/redisTest/6382/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf

查看容器运行状态

docker ps

检查主从同步配置

docker exec -it c0 bashroot@c0b98619a2da:/data# redis-cli -p 6380 -a 1234127.0.0.1:6380> info replication# Replicationrole:masterconnected_slaves:2slave0:ip=172.17.0.1,port=6381,state=online,offset=812,lag=0slave1:ip=172.17.0.1,port=6382,state=online,offset=812,lag=0master_replid:828fe844d602a47a942d183d0906966ba223c059master_replid2:0000000000000000000000000000000000000000master_repl_offset:812second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:812从库# Replicationrole:slavemaster_host:172.16.81.232master_port:6380master_link_status:upmaster_last_io_seconds_ago:10master_sync_in_progress:0slave_repl_offset:6916slave_priority:100slave_read_only:1connected_slaves:0master_replid:828fe844d602a47a942d183d0906966ba223c059master_replid2:0000000000000000000000000000000000000000master_repl_offset:6916second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:6916

检查主从同步配置 折叠原码

docker exec -it c0 bashroot@c0b98619a2da:/data# redis-cli -p 6380 -a 1234127.0.0.1:6380> info replication# Replicationrole:masterconnected_slaves:2slave0:ip=172.17.0.1,port=6381,state=online,offset=812,lag=0slave1:ip=172.17.0.1,port=6382,state=online,offset=812,lag=0master_replid:828fe844d602a47a942d183d0906966ba223c059master_replid2:0000000000000000000000000000000000000000master_repl_offset:812second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:812从库# Replicationrole:slavemaster_host:172.16.81.232master_port:6380master_link_status:upmaster_last_io_seconds_ago:10master_sync_in_progress:0slave_repl_offset:6916slave_priority:100slave_read_only:1connected_slaves:0master_replid:828fe844d602a47a942d183d0906966ba223c059master_replid2:0000000000000000000000000000000000000000master_repl_offset:6916second_repl_offset:-1repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:1repl_backlog_histlen:6916

sentinel配置 折叠原码# sentinal1port 26380dir /datalogfile "sentinel.log"# 指定要监视的redis实例 当2个sentinel认为master失效时 会开始failover流程sentinel monitor mymaster 172.16.81.232 6380 2# 当sentinel认为实例失效的时间(ms)sentinel down-after-milliseconds mymaster 10000# failover超时时间在(ms)内没完成,则 不会进行failoversentinel failover-timeout mymaster 60000# sentinel连接需要验证的master需要配置sentinel auth-pass mymaster 123456# sentinal2port 26381dir /datalogfile "sentinel.log"# 指定要监视的redis实例 当2个sentinel认为master失效时 会开始failover流程sentinel monitor mymaster 172.16.81.232 6380 2# 当sentinel认为实例失效的时间(ms)sentinel down-after-milliseconds mymaster 10000# failover超时时间在(ms)内没完成,则 不会进行failoversentinel failover-timeout mymaster 60000# sentinel连接需要验证的master需要配置sentinel auth-pass mymaster 123456# sentinal3port 26382dir /datalogfile "sentinel.log"# 指定要监视的redis实例 当2个sentinel认为master失效时 会开始failover流程sentinel monitor mymaster 172.16.81.232 6380 2# 当sentinel认为实例失效的时间(ms)sentinel down-after-milliseconds mymaster 10000# failover超时时间在(ms)内没完成,则 不会进行failoversentinel failover-timeout mymaster 60000# sentinel连接需要验证的master需要配置sentinel auth-pass mymaster 123456

sentinel状态 折叠原码dk exec -it b0 bashroot@b0032eb467d6:/data# redis-cli -p 26382127.0.0.1:26382> info Sentinel# SentinelSentinel_masters:1Sentinel_tilt:0Sentinel_running_scripts:0Sentinel_scripts_queue_length:0Sentinel_simulate_failure_flags:0master0:name=mymaster,status=ok,address=172.16.81.232:6380,slaves=2,Sentinels=3# 查看master的地址127.0.0.1:26382> Sentinel get-master-addr-by-name mymaster1) "172.16.81.232"2) "6380"

查看Sentinel日志,可以发现两个slave和其他两个Sentinel已经被发现:

d575993e0692d8b186a921e2b67b1930.png

测试阶段

  • 测试断掉master,是否会按照预期的发生failover,重新选择master:停止现有master容器docker stop c0
    发生了failover,重新选择master:(虽然6380的master没有运行,但还是被添加为了slave)failover1:X 15 Apr 2019 11:49:53.671 # +sdown master mymaster 172.16.81.232 63801:X 15 Apr 2019 11:49:53.731 # +new-epoch 11:X 15 Apr 2019 11:49:53.737 # +vote-for-leader 2a6578438619d67a76a817c0f308231579f1d4f4 11:X 15 Apr 2019 11:49:53.737 # +odown master mymaster 172.16.81.232 6380 #quorum 3/21:X 15 Apr 2019 11:49:53.737 # Next failover delay: I will not start a failover before Mon Apr 15 11:51:54 20191:X 15 Apr 2019 11:49:54.558 # +config-update-from Sentinel 2a6578438619d67a76a817c0f308231579f1d4f4 172.17.0.7 26382 @ mymaster 172.16.81.232 63801:X 15 Apr 2019 11:49:54.558 # +switch-master mymaster 172.16.81.232 6380 172.17.0.1 63821:X 15 Apr 2019 11:49:54.559 * +slave slave 172.17.0.1:6381 172.17.0.1 6381 @ mymaster 172.17.0.1 63821:X 15 Apr 2019 11:49:54.559 * +slave slave 172.16.81.232:6380 172.16.81.232 6380 @ mymaster 172.17.0.1 63821:X 15 Apr 2019 11:50:04.578 # +sdown slave 172.16.81.232:6380 172.16.81.232 6380 @ mymaster 172.17.0.1

e6a210c74dff39a13504fd31f7b49209.png

原master配置文件已经被重新

e7c00cacb832d188401a3fa7b137216a.png

重新添加master,此master还是会被当做slave,不会重新作为master:

启动原masterdocker start c0

添加slave1:X 15 Apr 2019 12:03:37.330 # -sdown slave 172.16.81.232:6380 172.16.81.232 6380 @ mymaster 172.17.0.1 63821:X 15 Apr 2019 12:03:48.486 * +slave slave 172.17.0.1:6380 172.17.0.1 6380 @ mymaster 172.17.0.1

58423caf550f726be5c663706984e652.png

Sentinel之间也会互相监视,对其他Sentinel重启:

sentinel感知1:X 15 Apr 2019 12:19:40.861 # +sdown Sentinel 58c20f1d11bcbd68b927fca77c7b85dafda565ba 172.17.0.6 26381 @ mymaster 172.17.0.1 63821:X 15 Apr 2019 12:20:25.295 # -sdown Sentinel 58c20f1d11bcbd68b927fca77c7b85dafda565ba 172.17.0.626381@ mymaster172.17.0.16382

Sentinel特性

  1. 故障转移时,判断一个master node是宕机了,需要大部分的Sentinel都同意才行,涉及到了分布式选举的问题
  2. Sentinel至少需要3个实例,来保证自己的健壮性
  3. Sentinel + redis主从的部署架构,是不会保证数据零丢失的,只能保证redis集群的高可用性

sdown和odown

  1. sdown和odown两种失败状态
  2. sdown是主观宕机,就一个Sentinel如果自己觉得一个master宕机了,那么就是主观宕机
  3. odown是客观宕机,如果quorum数量的Sentinel都觉得一个master宕机了,那么就是客观宕机
  4. sdown达成的条件:如果一个Sentinelping一个master,超过了is-master-down-after-milliseconds指定的毫秒数之后,就主观认为master宕机
  5. odown达成的条件:如果一个Sentinel在指定时间内,收到了quorum指定数量的其他Sentinel也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机

quorum和majority

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

master选举算法
如果一个master被认为odown了,而且majoritySentinel都允许了主备切换,那么某个Sentinel就会执行主备切换操作,此时首先要选举一个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比较小的那个slaveSentinel leader选举算法
参考:Raft协议,有Leader, Follower, Candidate三种角色

  • 1、某个Sentinel认定master sdown后,该Sentinel会先检查自己有没有投过票,如果自己已经投过票给其他Sentinel了,在2倍failover的超时时间自己就不会成为Leader相当于它是一个Follower
  • 2、如果该Sentinel还没投过票,那么它就成为Candidate
  • 3、和Raft协议描述的一样,成为Candidate,Sentinel需要完成几件事情
    • 1)更新failover状态为start
    • 2)当前epoch加1,相当于进入一个新term,在Sentinel中epoch就是Raft协议中的term
    • 3)更新自己的超时时间为当前时间随机加上一段时间,随机时间为1s内的随机毫秒数
    • 4)向其他节点发送is-master-down-by-addr命令请求投票命令会带上自己的epoch
    • 5)给自己投一票,在Sentinel中,投票的方式是把自己master结构体里的leader和leader_epoch改成投给的Sentinel和它的epoch
  • 4、其他Sentinel会收到Candidate的is-master-down-by-addr命令如果Sentinel当前epoch和Candidate传给他的epoch一样,说明他已经把自己master结构体里的leader和leader_epoch改成其他Candidate,相当于把票投给了其他Candidate投过票给别的Sentinel后,在当前epoch内自己就只能成为Follower
  • 5、Candidate会不断的统计自己的票数,直到他发现认同他成为Leader的票数超过一半而且超过它配置的quorum
  • 6、如果在一个选举时间内,Candidate没有获得超过一半且超过它配置的quorum的票数,自己的这次选举就失败了
  • 7、如果在一个epoch内,没有一个Candidate获得更多的票数那么等待超过2倍故障转移的超时时间后,Candidate增加epoch重新投票
  • 8、如果某个Candidate获得超过一半且超过它配置的quorum的票数,那么它就成为了Leader
  • 9、与Raft协议不同,Leader并不会把自己成为Leader的消息发给其他Sentinel其他Sentinel等待Leader从slave选出master后,检测到新的master正常工作后,就会去掉客观下线的标识,从而不需要进入故障转移流程

configuration epoch
Sentinel会对一套redis master+slave进行监控,有相应的监控的配置
执行切换的那个Sentinel,会从要切换到的新master(salve->master)那里得到一个configuration epoch,这就是一个version号,每次切换的version号都必须是唯一的
如果第一个选举出的Sentinel切换失败了,那么其他Sentinel,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的version号configuraiton传播
Sentinel完成切换之后,会在自己本Sentinel地更新生成最新的master配置,然后同步给其他的Sentinel,就是通过之前说的pub/sub消息机制
这里之前的version号就很重要了,因为各种消息都是通过一个channel去发布和监听的,所以一个Sentinel完成一次新的切换之后,新的master配置是跟着新的version号的
其他的Sentinel都是根据版本号的大小来更新自己的master配置的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值