大家好,我是七哥。

上一篇文章,我带大家学习了,大家也都明白了「主从复制」可以应对高并发读的场景,因为从库宕机依然可以将请求发送给主库或者其他从库,但是 宕机,整个集群就只能响应读操作,写请求无法再执行了。

也就是说主从复制这个方案最大的问题就在于 无法自动选择一个 Slave 切换为 ,不具备故障自动切换的能力。

因此如果仅仅是主从复制,这完成不能称之为高可用架构,那什么是高可用呢?我们在公司应该经常听到架构的全年可用达到 5个9、6个9之类的术语,其实就是说我们的服务要在一年中达到 99.9999% 的时间是可用的,那实现高可用就需要用到我们今天聊到的哨兵以及下一篇带来的Redis集群:,大家可以关注我,及时获取更多技术干货。

这里再补充一点:redis主从复制的作用中有这么一句话 “主从复制是高可用的基石”,所以搞清楚原理是非常必要的。

0. 内容概要

redis哨兵模式_哨兵模式redis怎么启动_哨兵模式redis配置

通过本文的学习你可以掌握关于哨兵相关的这些知识点:

坚持看完对于你面试和工作用处别提有多大了,我们就不废话了,开始上菜!

Redis 的哨兵模式到了 redis 2.8 版本之后才有的。

1. 什么是Redis哨兵

我们可以先思考下,**Redis 主从复制的缺点 **是没有办法对 进行动态选举(宕机后,需要重新选举)。

哨兵模式redis配置_哨兵模式redis怎么启动_redis哨兵模式

老大哥 挂掉后,小弟 slave 们嗷嗷待哺,用户的增量数据写不进来了。这个时候应运而生,就将我们的哨兵带到了程序员的面前。

哨兵说: 老大哥走了,小弟们谁来出头接任老大,这个问题我帮你解决嘛,毛毛雨啦!我作为一个公平公正的第三方观察者,从你们内部这4个小弟中选出一个天选之人,你们都认他当老大不就好了。同时,一旦我选出了新老大,就算之前的 老大哥诈尸又回来了,他也只配以小弟的身份加入我们的圈子。

通过上面哨兵老哥的自述redis哨兵模式,我们心里已经明白了它大概是用来做什么的了,下面我们就正儿八经的给哨兵一个定义:

哨兵() 是一个分布式系统,你可以在一个架构中运行多个哨兵() 进程, 这些进程使用 协议(基于流行病传播方式的节点或者进程之间信息交换的协议,在分布式系统中被广泛使用) 来接收关于是否下线的信息,并使用投票协议( ) 来决定是否执行自动故障迁移,以及选择哪个 Slave 作为新的 (raft算法) 。

2. 哨兵的作用

通过上面稍等的自述对话,我们知道了 (哨兵)进程是用于 监控 Redis 集群中 主服务器工作的状态,在 主服务器发生故障的时候,可以实现 和 Slave 服务器的切换,保证系统的高可用( HA );

接下来我们就先用比较干巴的语言描述下这个哨兵到底在工作中到底干了什么事情,然后在下文的工作原理会一一谈到。

Redis的哨兵() 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:

redis哨兵模式_哨兵模式redis怎么启动_哨兵模式redis配置

每个哨兵会向其它哨兵、、slave 定时发送消息,以确认对方是否“活”着,如果发现对方在 指定时间(可配置)内未回应,则暂时认为对方已挂 (所谓的 "主观认为宕机" , Down,简称sdown)。

若 “哨兵群” 中的多数哨兵都报告这个 没响应,系统才认为该 老大哥 "彻底死亡" (即:客观上的真正down机, Down,简称odown)。

哨兵模式redis配置_哨兵模式redis怎么启动_redis哨兵模式

如图所示,主观下线是某一个哨兵自己认为宕机,而客观下线是该哨兵与其他哨兵沟通后,多数的哨兵都认为老大哥嗝屁了。同时配置哨兵时应该配置为单数(自己想下为什么呢,有疑问评论区留言)。

然后通过一定的投票算法(其实就是 raft算法,这块如果感兴趣我们后面也可以安排一篇来详细介绍),从剩下的slave节点中,选一台提升为新大哥 ,然后自动修改其它redis服务器的相关配置(slave机器认的大哥)。

这里提一嘴:哨兵其实也是一台 Redis 服务器,只是不对外提供任何服务。稍后我们在配置时,你会看到实际上哨兵只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 -- 选项来启动哨兵。

哨兵的主要工作任务:

redis哨兵模式_哨兵模式redis怎么启动_哨兵模式redis配置

3. 哨兵模式配置

我本地 Redis 安装目录:/usr/local/redis

cp sentinel.conf  /usr/local/redis/etc

哨兵使用的配置文件是 .conf,我们来解读下这个配置文件,看看需要做什么?

# sentinel monitor    
sentinel monitor mymaster 192.168.137.6 6379 1
#后台运行
daemonize yes

非常简单,我们只需要指定哨兵需要监控的 是谁就好了。

-name:可以自己自定义命名主节点的名字,只要是字段 A-z、数字0-9、“.-_” 这些字符组成的就行,我这里命令为 。

ip:监控的 节点的 ip。

port: 节点的端口号。

:法定人数,这个是指有几个哨兵认为老大哥挂了,就客观下线,通过设置为哨兵总数的一半加一。

其它 .conf 配置项说明

将所有配置项都给大家列出了详细说明,建议都看下,就能对实现原理有进一步的理解。


# 哨兵sentinel实例运行的端口 默认26379
port 26379

# 哨兵sentinel的工作目录
dir /tmp

# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor    
sentinel monitor mymaster 127.0.0.1 6379 1

# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码,无密码可忽略此配置
# sentinel auth-pass  
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

# 指定多少毫秒之后 主节点没有应答哨兵sentinel  此时,哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds  
sentinel down-after-milliseconds mymaster 30000

# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs  
sentinel parallel-syncs mymaster 1

# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout  
sentinel failover-timeout mymaster 180000

# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script  
sentinel notification-script mymaster /var/redis/notify.sh

# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
#       
# 目前总是“failover”,
# 是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script  
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

./redis-sentinel sentinel.conf

注意:

当启动哨兵模式之后,如果你的服务器宕机之后,哨兵自动会在从redis服务器里面 投票选举一个主服务器出来;这个主服务器也可以进行读写操作!

如果之前宕机的主服务器已经修好,可以正式运行了。那么这个服务器只能进行读的操作,也就说前大哥现在变为小弟了。

大家可以进入 ./redis-cli,输入info ,查看你的状态信息;

redis哨兵模式_哨兵模式redis配置_哨兵模式redis怎么启动

4. 哨兵工作原理

配置完哨兵后,就需要对其工作原理进行解析了,只有知道其工作流程,才能对哨兵有更好的理解。

我会尽量讲解的通俗易懂,让你阅读起来不那么枯燥乏味,结合上面掌握的哨兵作用以及操作配置,理解起来就非常容易了。

进入正题,哨兵作用是监控、通知、故障转移。那么工作原理也是围绕这三点来讲的。

监控工作流程

哨兵模式redis怎么启动_哨兵模式redis配置_redis哨兵模式

哨兵启动后根据配置向 发送info指令,获取并且保存所有哨兵状态,主节点和从节点的信息;

主节点 会记录所有 从节点和与它连接的哨兵实例的信息;

哨兵会根据在主节点拿到的从节点信息,给对应的从节点建立连接后发送info指令;

接着哨兵2来了,同样的也会给主节点发送 info 指令,同时拿到了从节点和哨兵的实例信息;

此时哨兵2也会保存跟哨兵1一样的信息,只不过它保存的哨兵信息是2个;

这个时候为了每个哨兵的信息都一致它们之间建立了一个发布订阅,互相发送 ping 命令 保证信息长期对称;

当再来一个哨兵3时,也会做同样的事情,给主节点和从节点发送info,并且跟哨兵1和哨兵2建立连接;

从服务器是如何与主服务器同步数据的?

从服务器默认以每秒一次的频率,向主服务器发送命令:

# replication_offset 指从服务器当前的复制偏移量。
REPLCONF ACK

举个例子:如果因为网络故障,主服务器传播给从服务器的写命令在半路丢失,那么当从服务器向主服务器发送命令: ACK 时,主服务器将发觉从服务器当前的复制偏移量少于自己的复制偏移量,然后主服务器就会根据从服务器提交的复制偏移量,在复制积压缓冲区里面找到从服务器缺少的数据,并将这些数据重新发送给从服务器。

这一点面试经常问,如果你能回答到原理这个层面,征服面试官是不成问题的了。

心跳检测的作用什么?

检测主服务器的网络连接状态;

通过向主服务器发送 INFO 命令,可以列出从服务器列表,可以看出 slave 最后一次向 发送命令距离现在过了多少秒。

localhost:6377> info replication
# Replication
role:master
connected_slaves:2
# lag=0,刚刚发送过REPLCONF ACK 命令
slave0:ip=127.0.0.1,port=6379,state=online,offset=110180,lag=0 
# lag=1,1秒之前发送过REPLCONF ACK 命令
slave1:ip=127.0.0.1,port=6378,state=online,offset=110180,lag=1 
master_replid:55c2177dd69fc21dbea4e9f8a3f4fb0ee948855d
master_replid2:a80967516d1b0821c315fd2eb550f2ff0597010c
master_repl_offset:110313
second_repl_offset:25348
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:11612
repl_backlog_histlen:98702

从服务器的 lag 的值应该在 0 或 1 之间跳动redis哨兵模式,如果超过1则说明主从之间的连接有故障。

辅助实现 min- 功能;

这是一个集群安全的检查项,Redis 可以通过配置防止主服务器在不安全的情况下执行写命令;

min-slaves-to-write 3
min-slaves-max-lag 10

上面的配置表示:从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器将拒绝执行写命令。这里的延迟值就是上面 INFO 命令的lag值。

通知工作流程

哨兵会给主从的所有节点发送命令获取其状态,并且会把信息发布到哨兵的订阅里。

redis哨兵模式_哨兵模式redis怎么启动_哨兵模式redis配置

故障转移原理(重要)

哨兵模式redis配置_redis哨兵模式_哨兵模式redis怎么启动

哨兵会一直给主节点发送 :hello,直到哨兵收不到响应而报出 sdown。哨兵报出主节点 sdown 后还没有完,哨兵还会往内网里发布消息给其它哨兵说明这个主节点挂了。发送的指令是 is--down-by--port。

其余的哨兵接收到指令后,心想,主节点挂了吗?让我去看看到底挂没挂。发送的信息也是 hello,如果发现确实收不到响应而报出 sdown,这些哨兵也发送指令 is--down-by--port 到自己的内网,就这样大家都收到了哨兵内部群发的这个 已经挂了的消息,然后汇总计票,超过一半就认为这个家伙确实挂了,然后就会修改其状态为 odown。当一个哨兵认为主节点挂了标记的是 sdown,当过半数哨兵都认为挂了其标记的状态是 odown,这也就是配置哨兵为什么配置单数的原因。

对于一个哨兵认为主节点挂了称之为主观下线,超半数哨兵认为主节点挂了称之为客观下线。

一旦被认为主节点客观下线后,哨兵就会进行下一步操作选举新大哥。

这时哨兵内部已经检测到问题所在了,那么到底是哪个哨兵去负责推选新的主节点呢!总不能张三、李四、王麻子都去选举吧,这样就乱套了。于是就需要先在所有的哨兵里选出领头的,那么是如何选的呢!

哨兵模式redis怎么启动_redis哨兵模式_哨兵模式redis配置

这个时候呢!5个就在一起开会了,所有的哨兵都在一个内网中,然后他们会做一件事情就是五个会同时发送指令 is--down-by--port 并且携带上自己竞选次数和runid。

每个 既是参选者也是投票者,每个都有一票,信封就代表自己的投票权。

选择规则我来举个例子你应该就懂了:当和同时把指令发送到哨兵内部群里准备竞选时,这个时候就说我先接到谁的指令就把票投给谁。假如发的早,那么的票就会投给。

按照这样的规则一直发起投票直到某一个时间点有一个的票数为总数量的一半之多。假设说是的票数满足总哨兵数量的一半之多后,就会当选。这个时候就进行到了下一个阶段。

redis哨兵模式_哨兵模式redis怎么启动_哨兵模式redis配置

在上边哨兵已经选出了 为代表去所有的从节点找出一个作为主节点。这个挑选主节点不是随便拿一个是有一定的规则的。但是本文就不对具体的选举规则做详解了,其实就是 Raft 算法,感兴趣的话可以留言,我们后面安排一篇仔细聊聊。

这里简单说下选举新需要满足的条件:

选出新的主节点后就要对所有的节点发送指令了,召集所有兄弟,告知新老大的上位。然后 slave 从新老大上同步数据,广播告知所有客户端新老大的身份,至此切换完成。

5. 总结

关于哨兵的所有知识点就已经说完了,最重要的就是哨兵的作用和工作原理了。面试时也是考察redis高可用的一个重点,我们再来简单总结下。

Redis主从复制算是高可用实现的基础,Redis 哨兵机制实现了主从库的自动切换,在高可用的道路上算是又迈出了一大步。

哨兵主要用来做下面三件事

哨兵工作原理

这就是Redis哨兵集群的所有内容了,感谢大家的观看。如有错误,欢迎指正,七哥会及时纠正。~

下一篇「七哥聊编程」将带来 「官方推荐的Redis高可用方案:」 ,关注我,获取真正的硬核知识点。

另外技术读者群也开通了,添加七哥微信回复:进群,一起成长交流、围观朋友圈。群里有 N 多大厂的大佬,也有毕业萌新,还可内推哦。

哨兵模式redis配置_redis哨兵模式_哨兵模式redis怎么启动

redis哨兵模式_哨兵模式redis怎么启动_哨兵模式redis配置

码字不易,觉得内容对你有帮助,希望你能花 0.1秒 点个赞哟~ 你小小的点赞永远是我持续创作的动力,谢谢你(疯狂比心)~

哨兵模式redis怎么启动_哨兵模式redis配置_redis哨兵模式

作者介绍:七哥,一个热爱技术的程序员,写文章也经常拍视频,专注于 Java 技术干货分享,愿望是陪家人平淡快乐的度过一生!

往期推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注