Redis哨兵是个啥?实现高可用的秘密原来在这里
mhr18 2024-10-26 10:54 17 浏览 0 评论
上一篇文章,我带大家学习了《Redis主从复制的原理》,大家也都明白了「主从复制」可以应对高并发读的场景,因为从库宕机依然可以将请求发送给主库或者其他从库,但是 Master 宕机,整个集群就只能响应读操作,写请求无法再执行了。
也就是说主从复制这个方案最大的问题就在于 无法自动选择一个 Slave 切换为 Master,不具备故障自动切换的能力。
因此如果仅仅是主从复制,这完成不能称之为高可用架构,那什么是高可用呢?我们在公司应该经常听到架构的全年可用达到 5个9、6个9之类的术语,其实就是说我们的服务要在一年中达到 99.9999% 的时间是可用的,那实现高可用就需要用到我们今天聊到的哨兵以及下一篇带来的Redis集群:RedisCluster,大家可以关注我,及时获取更多技术干货。
这里再补充一点:redis主从复制的作用中有这么一句话 “主从复制是高可用的基石”,所以搞清楚原理是非常必要的。
0. 内容概要
通过本文的学习你可以掌握关于哨兵相关的这些知识点:
- 什么是Redis哨兵
- 哨兵的作用是什么
- Redis哨兵如何配置
- 哨兵的工作原理
坚持看完对于你面试和工作用处别提有多大了,我们就不废话了,开始上菜!
Redis 的哨兵模式到了 redis 2.8 版本之后才有的。
1. 什么是Redis哨兵
我们可以先思考下,**Redis 主从复制的缺点 **是没有办法对 master 进行动态选举(master宕机后,需要重新选举master)。
老大哥 master 挂掉后,小弟 slave 们嗷嗷待哺,用户的增量数据写不进来了。这个时候应运而生,就将我们的哨兵带到了程序员的面前。
哨兵说:master 老大哥走了,小弟们谁来出头接任老大,这个问题我帮你解决嘛,毛毛雨啦!我作为一个公平公正的第三方观察者,从你们内部这4个小弟中选出一个天选之人,你们都认他当老大不就好了。同时,一旦我选出了新老大,就算之前的 master 老大哥诈尸又回来了,他也只配以小弟的身份加入我们的圈子。
通过上面哨兵老哥的自述,我们心里已经明白了它大概是用来做什么的了,下面我们就正儿八经的给哨兵一个定义:
哨兵(sentinel) 是一个分布式系统,你可以在一个架构中运行多个哨兵(sentinel) 进程, 这些进程使用 gossip协议(基于流行病传播方式的节点或者进程之间信息交换的协议,在分布式系统中被广泛使用) 来接收关于Master是否下线的信息,并使用投票协议(agreement protocols) 来决定是否执行自动故障迁移,以及选择哪个 Slave 作为新的 Master (raft算法) 。
2. 哨兵的作用
通过上面稍等的自述对话,我们知道了 Sentinel (哨兵)进程是用于 监控 Redis 集群中 Master主服务器工作的状态,在 Master 主服务器发生故障的时候,可以实现 Master 和 Slave 服务器的切换,保证系统的高可用( HA );
接下来我们就先用比较干巴的语言描述下这个哨兵到底在工作中到底干了什么事情,然后在下文的工作原理会一一谈到。
Redis的哨兵(sentinel) 系统用于管理多个 Redis 服务器,该系统执行以下三个任务:
- 监控( Monitoring ) :监控谁?哨兵( sentinel ) 会不断地检查你的 Master 和 Slave 是否运作正常。
- 通知( Notification ) :哨兵检测的服务器出现问题时,会向其他的哨兵发送通知,哨兵之间就相当于一个微信群,每个哨兵发现的问题都会发在这个群里。
- 自动故障迁移( Automatic failover ) :当检测到主节点宕机后,断开与宕机主节点连接的所有从节点,在从节点中选取一个作为主节点,然后将其他的从节点连接到这个最新主节点的上。并且告知客户端最新的服务器地址。
每个哨兵会向其它哨兵、master、slave 定时发送消息,以确认对方是否“活”着,如果发现对方在 指定时间(可配置)内未回应,则暂时认为对方已挂 (所谓的 "主观认为宕机" ,Subjective Down,简称sdown)。
若 “哨兵群” 中的多数哨兵都报告这个 master 没响应,系统才认为该 master 老大哥 "彻底死亡" (即:客观上的真正down机,Objective Down,简称odown)。
如图所示,主观下线是某一个哨兵自己认为master宕机,而客观下线是该哨兵与其他哨兵沟通后,多数的哨兵都认为老大哥嗝屁了。同时配置哨兵时应该配置为单数(自己想下为什么呢,有疑问评论区留言)。
然后通过一定的投票算法(其实就是 raft算法,这块如果感兴趣我们后面也可以安排一篇来详细介绍),从剩下的slave节点中,选一台提升为新大哥 master,然后自动修改其它redis服务器的相关配置(slave机器认的大哥)。
这里提一嘴:哨兵其实也是一台 Redis 服务器,只是不对外提供任何服务。稍后我们在配置时,你会看到实际上哨兵只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵。
哨兵的主要工作任务:
3. 哨兵模式配置
我本地 Redis 安装目录:/usr/local/redis
- 拷贝sentinel.conf 到etc目录
cp sentinel.conf /usr/local/redis/etc
哨兵使用的配置文件是 sentinel.conf,我们来解读下这个配置文件,看看需要做什么?
- 修改sentinel.conf配置文件
# sentinel monitor <master-name> <master ip> <master port> <quorum>
sentinel monitor mymaster 192.168.137.6 6379 1
#后台运行
daemonize yes
非常简单,我们只需要指定哨兵需要监控的 master 是谁就好了。
master-name:可以自己自定义命名主节点的名字,只要是字段 A-z、数字0-9、“.-_” 这些字符组成的就行,我这里命令为 mymaster。
master ip:监控的 master 节点的 ip。
master port:master 节点的端口号。
quorum:法定人数,这个是指有几个哨兵认为老大哥master挂了,就客观下线,通过设置为哨兵总数的一半加一。
其它 sentinel.conf 配置项说明
将所有配置项都给大家列出了详细说明,建议都看下,就能对实现原理有进一步的理解。
# 哨兵sentinel实例运行的端口 默认26379
port 26379
# 哨兵sentinel的工作目录
dir /tmp
# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码,无密码可忽略此配置
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时,哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
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 <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh
- 通过 redis-sentinel 启动哨兵服务
./redis-sentinel sentinel.conf
注意:
- 当启动哨兵模式之后,如果你的master服务器宕机之后,哨兵自动会在从redis服务器里面 投票选举一个master主服务器出来;这个主服务器也可以进行读写操作!
- 如果之前宕机的主服务器已经修好,可以正式运行了。那么这个服务器只能进行读的操作,也就说前大哥现在变为小弟了。
- 大家可以进入 ./redis-cli,输入info replication,查看你的状态信息;
4. 哨兵Sentinel工作原理
配置完哨兵后,就需要对其工作原理进行解析了,只有知道其工作流程,才能对哨兵有更好的理解。
我会尽量讲解的通俗易懂,让你阅读起来不那么枯燥乏味,结合上面掌握的哨兵作用以及操作配置,理解起来就非常容易了。
进入正题,哨兵作用是监控、通知、故障转移。那么工作原理也是围绕这三点来讲的。
监控工作流程
- 哨兵启动后根据配置向 master 发送info指令,获取并且保存所有哨兵状态,主节点和从节点的信息;
- 主节点 master 会记录所有 从节点和与它连接的哨兵实例的信息;
- 哨兵会根据在主节点拿到的从节点信息,给对应的从节点建立连接后发送info指令;
- 接着哨兵2来了,同样的也会给主节点发送 info 指令,同时拿到了从节点和哨兵的实例信息;
- 此时哨兵2也会保存跟哨兵1一样的信息,只不过它保存的哨兵信息是2个;
- 这个时候为了每个哨兵的信息都一致它们之间建立了一个发布订阅,互相发送 ping 命令 保证信息长期对称;
- 当再来一个哨兵3时,也会做同样的事情,给主节点和从节点发送info,并且跟哨兵1和哨兵2建立连接;
从服务器是如何与主服务器同步数据的?
从服务器默认以每秒一次的频率,向主服务器发送命令:
# replication_offset 指从服务器当前的复制偏移量。
REPLCONF ACK <replication_offset>
举个例子:如果因为网络故障,主服务器传播给从服务器的写命令在半路丢失,那么当从服务器向主服务器发送命令:REPLCONF ACK <replication_offset> 时,主服务器将发觉从服务器当前的复制偏移量少于自己的复制偏移量,然后主服务器就会根据从服务器提交的复制偏移量,在复制积压缓冲区里面找到从服务器缺少的数据,并将这些数据重新发送给从服务器。
这一点面试经常问,如果你能回答到原理这个层面,征服面试官是不成问题的了。
心跳检测的作用什么?
- 检测主服务器的网络连接状态;
通过向主服务器发送 INFO replication 命令,可以列出从服务器列表,可以看出 slave 最后一次向 master 发送命令距离现在过了多少秒。
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 之间跳动,如果超过1则说明主从之间的连接有故障。
- 辅助实现 min-slaves 功能;
这是一个集群安全的检查项,Redis 可以通过配置防止主服务器在不安全的情况下执行写命令;
min-slaves-to-write 3
min-slaves-max-lag 10
上面的配置表示:从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器将拒绝执行写命令。这里的延迟值就是上面 INFO replication 命令的lag值。
通知工作流程
Sentinel哨兵会给主从的所有节点发送命令获取其状态,并且会把信息发布到哨兵的订阅里。
故障转移原理(重要)
- 哨兵会一直给主节点发送 publish sentinel :hello,直到哨兵收不到响应而报出 sdown。哨兵报出主节点 sdown 后还没有完,哨兵还会往内网里发布消息给其它哨兵说明这个主节点挂了。发送的指令是 sentinel is-master-down-by-address-port。
- 其余的哨兵接收到指令后,心想,主节点挂了吗?让我去看看到底挂没挂。发送的信息也是 hello,如果发现确实收不到响应而报出 sdown,这些哨兵也发送指令sentinel is-master-down-by-address-port 到自己的内网,就这样大家都收到了哨兵内部群发的这个 master 已经挂了的消息,然后汇总计票,超过一半就认为这个家伙确实挂了,然后就会修改其状态为 odown。当一个哨兵认为主节点挂了标记的是 sdown,当过半数哨兵都认为挂了其标记的状态是 odown,这也就是配置哨兵为什么配置单数的原因。
- 对于一个哨兵认为主节点挂了称之为主观下线,超半数哨兵认为主节点挂了称之为客观下线。
- 一旦被认为主节点客观下线后,哨兵就会进行下一步操作选举新大哥。
这时哨兵内部已经检测到问题所在了,那么到底是哪个哨兵去负责推选新的主节点呢!总不能张三、李四、王麻子都去选举吧,这样就乱套了。于是就需要先在所有的哨兵里选出领头的,那么是如何选的呢!
这个时候呢!5个sentinel就在一起开会了,所有的哨兵都在一个内网中,然后他们会做一件事情就是五个sentinel会同时发送指令sentinel is-master-down-by-address-port 并且携带上自己竞选次数和runid。
每个 sentinel 既是参选者也是投票者,每个sentinel都有一票,信封就代表自己的投票权。
选择规则我来举个例子你应该就懂了:当sentinel1和sentinel4同时把指令发送到哨兵内部群里准备竞选时,sentinel2这个时候就说我先接到谁的指令就把票投给谁。假如sentinel1发的早,那么sentinel2的票就会投给sentinel1。
按照这样的规则一直发起投票直到某一个时间点有一个sentinel的票数为总sentinel数量的一半之多。假设说是sentinel1的票数满足总哨兵数量的一半之多后,sentinel1就会当选。这个时候就进行到了下一个阶段。
在上边哨兵已经选出了sentinel1 为代表去所有的从节点找出一个作为主节点。这个挑选主节点不是随便拿一个是有一定的规则的。但是本文就不对具体的选举规则做详解了,其实就是 Raft 算法,感兴趣的话可以留言,我们后面安排一篇仔细聊聊。
这里简单说下选举新master需要满足的条件:
- 响应慢的干掉,sentinel会给所有的redis发送信息,响应速度慢的就会被干掉;
- 判断 offset 偏移量,判断数据同步性,假如说 slave4 的 offset 为90, slave5偏移量为100 那么哨兵就会认为slave4的网络是不是有问题啊!于是就会选slave5为新的主节点。那如果说是slave4和slave5的offset相同呢!那就看下一个判断;
- 最后一步就是判断runid了,也就是职场中的论资排辈了,时间早的上位。
选出新的主节点后就要对所有的节点发送指令了,召集所有兄弟,告知新老大的上位。然后 slave 从新老大master上同步数据,广播告知所有客户端新老大的身份,至此切换完成。
5. 总结
关于哨兵的所有知识点就已经说完了,最重要的就是哨兵的作用和工作原理了。面试时也是考察redis高可用的一个重点,我们再来简单总结下。
Redis主从复制算是高可用实现的基础,Redis 哨兵机制实现了主从库的自动切换,在高可用的道路上算是又迈出了一大步。
哨兵主要用来做下面三件事
- 监控 master 与 slave 运行状态,判断是否客观下线;
- master 客观下线后,选择一个 slave 切换成 master;
- 通知 slave 和客户端新 master 信息。
哨兵工作原理
- 首先监控 master、slave,并且所有的哨兵之间互相同步信息;
- 哨兵向订阅里边发布信息;
- 哨兵发现主节点下线;
- 哨兵开启投票竞选负责人;
- 由负责人推选新的主节点;
- 新的主节点断开原主节点,并且通知其他的从节点连接新的主节点,原主节点上线后作为从节点连接;
这就是Redis哨兵集群的所有内容了,感谢大家的观看。如有错误,欢迎指正~
相关推荐
- B站收藏视频失效?mybili 收藏夹备份神器完整部署指南
-
本内容来源于@什么值得买APP,观点仅代表作者本人|作者:羊刀仙很多B站用户都有过类似经历:自己精心收藏的视频突然“消失”,点开一看不是“已被删除”,就是“因UP主设置不可见”。而B站并不会主动通知...
- 中间件推荐初始化配置
-
Redis推荐初始化配置bind0.0.0.0protected-modeyesport6379tcp-backlog511timeout300tcp-keepalive300...
- Redis中缓存穿透问题与解决方法
-
缓存穿透问题概述在Redis作为缓存使用时,缓存穿透是常见问题。正常查询流程是先从Redis缓存获取数据,若有则直接使用;若没有则去数据库查询,查到后存入缓存。但当请求的数据在缓存和数据库中都...
- 后端开发必看!Redis 哨兵机制如何保障系统高可用?
-
你是否曾在项目中遇到过Redis主服务器突然宕机,导致整个业务系统出现数据读取异常、响应延迟甚至服务中断的情况?面对这样的突发状况,作为互联网大厂的后端开发人员,如何快速恢复服务、保障系统的高可用...
- Redis合集-大Key处理建议
-
以下是Redis大Key问题的全流程解决方案,涵盖检测、处理、优化及预防策略,结合代码示例和最佳实践:一、大Key的定义与风险1.大Key判定标准数据类型大Key阈值风险场景S...
- 深入解析跳跃表:Redis里的"老六"数据结构,专治各种不服
-
大家好,我是你们的码农段子手,今天要给大家讲一个Redis世界里最会"跳科目三"的数据结构——跳跃表(SkipList)。这货表面上是个青铜,实际上是个王者,连红黑树见了都要喊声大哥。...
- Redis 中 AOF 持久化技术原理全解析,看完你就懂了!
-
你在使用Redis的过程中,有没有担心过数据丢失的问题?尤其是在服务器突然宕机、意外断电等情况发生时,那些还没来得及持久化的数据,是不是让你夜不能寐?别担心,Redis的AOF持久化技术就是...
- Redis合集-必备的几款运维工具
-
Redis在应用Redis时,经常会面临的运维工作,包括Redis的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。接下来,从这三个方面,介绍一些工具。先来学习下监控Redis实时...
- 别再纠结线程池大小 + 线程数量了,没有固定公式的!
-
我们在百度上能很轻易地搜索到以下线程池设置大小的理论:在一台服务器上我们按照以下设置CPU密集型的程序-核心数+1I/O密集型的程序-核心数*2你不会真的按照这个理论来设置线程池的...
- 网络编程—IO多路复用详解
-
假如你想了解IO多路复用,那本文或许可以帮助你本文的最大目的就是想要把select、epoll在执行过程中干了什么叙述出来,所以具体的代码不会涉及,毕竟不同语言的接口有所区别。基础知识IO多路复用涉及...
- 5分钟学会C/C++多线程编程进程和线程
-
前言对线程有基本的理解简单的C++面向过程编程能力创造单个简单的线程。创造单个带参数的线程。如何等待线程结束。创造多个线程,并使用互斥量来防止资源抢占。会使用之后,直接跳到“汇总”,复制模板来用就行...
- 尽情阅读,技术进阶,详解mmap的原理
-
1.一句话概括mmapmmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。这样,进程不仅能像访问内存一样读写文件,多个进程...
- C++11多线程知识点总结
-
一、多线程的基本概念1、进程与线程的区别和联系进程:进程是一个动态的过程,是一个活动的实体。简单来说,一个应用程序的运行就可以被看做是一个进程;线程:是运行中的实际的任务执行者。可以说,进程中包含了多...
- 微服务高可用的2个关键技巧,你一定用得上
-
概述上一篇文章讲了一个朋友公司使用SpringCloud架构遇到问题的一个真实案例,虽然不是什么大的技术问题,但如果对一些东西理解的不深刻,还真会犯一些错误。这篇文章我们来聊聊在微服务架构中,到底如...
- Java线程间如何共享与传递数据
-
1、背景在日常SpringBoot应用或者Java应用开发中,使用多线程编程有很多好处,比如可以同时处理多个任务,提高程序的并发性;可以充分利用计算机的多核处理器,使得程序能够更好地利用计算机的资源,...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)