在《Redis:主从复制》的最后,我们提到“从节点持久化”,在一个典型的主从架构的Redis系统中,从节点在整个系统中起到数据冗余备份和读写分离的作用。当主节点遇到异常中断服务后,开发者可以通过手动的方式选择一个从节点来升级为主节点,以使得系统能够继续对外提供服务。然而整个过程相对麻烦且需要人工介入,难以实现自动化。为此,Redis提供哨兵工具来实现自动化的系统监控和故障恢复功能。
1. 什么是哨兵
哨兵的作用就是监控Redis系统的运行状态,它的功能包括以下两个:
(1)集群监控:监控主节点和从节点是否正常运行;
(2)故障转移:主节点出现故障时自动将从节点转换为主节点。
哨兵是一个独立的进程,在一个一主多从的典型架构中,使用哨兵的架构图如下:
我们也可以使用多个哨兵进行监控任务以保证系统足够稳健(需要注意的是哨兵之间也会互相监控),如下图:
2. 入门案例
在理解哨兵的原理之前,我们先来使用哨兵,了解一下哨兵是如何工作的。先来看看服务器列表:
服务器ip | 端口号 | 角色 |
---|---|---|
192.168.1.19 | 6379 | Redis主节点 |
192.168.1.19 | 26379 | 哨兵服务 |
192.168.1.20 | 6379 | Redis从节点1 |
192.168.1.21 | 6379 | Redis从节点2 |
一主多从的架构搭建步骤在《Redis:主从复制》中已经描述,这里不再描述。
2.1 哨兵服务
在redis配置文件的同级目录下新建sentinel.conf
,内容如下:
# 配置端口
port 26379
# 以守护进程模式启动
#daemonize yes
# 监控的IP 端口号 名称 sentinel通过投票后认为mater宕机的数量
sentinel monitor node1_redis_master 192.168.1.19 6379 1
# 日志文件名
#logfile "sentinel_26379.log"
# 存放备份文件以及日志等文件的目录
#dir "/usr/local/redis"
# 30秒ping不通主节点的信息,主观认为master宕机
sentinel down-after-milliseconds node1_redis_master 10000
# 故障转移后重新主从复制,1表示串行,>1并行
#sentinel parallel-syncs node1_redis_master 1
# 故障转移开始,三分钟内没有完成,则认为转移失败
#sentinel failover-timeout node1_redis_master 180000
# 如果redis服务器配置了密码连接
#sentinel auth-pass node1_redis_master 123
其中node1_redis_master
:监控的主节点名称,我们可以随意指定(名字由大小写字母、数字和“.-_”这3个字符组成);后两个参数表示主节点的ip地址和端口号(哨兵只需要配置其监控主节点即可);最后的1表示最低通过票数。接下来启动哨兵服务1的进程:
redis-sentinel /etc/redis/sentinel.conf
+salve
表示发现了从节点,现在哨兵已经在监控这3个Redis服务了。
2.2 关闭主节点
接下来我们通过将主节点192.168.1.19
的Redis服务关闭,看下哨兵在这个过程做了什么。
(1)关闭主节点的Redis服务
redis-cli shutdown
(2)等待指定时间后(默认30s),哨兵会输出如下内容:
其中+sdown
表示哨兵主观认为主节点停止服务了,而+odown
表示哨兵客观认为主节点停止服务了。
(3)故障恢复
+try-failover
表示哨兵开始进行故障恢复;-failover-end
表示哨兵完成故障恢复;-switch-master
表示切换主节点,最终从节点2升级为主节点。
同时两个+slave
则列出新的主节点的两个从节点,其节点ip分别为192.168.1.19
和192.168.1.20
。其中19服务器的Redis服务仍处于关闭状态,所以是+sdown
主观下线,整个故障恢复过程就此完成。
2.3 重启旧的主节点(19服务器的Redis)
重启旧的主节点后,-sdown
表示19服务器的Redis已经启动,+convert-to-slave
表示将其转换成新的主节点的从节点。
3. 实现原理
一个哨兵进程在启动的时候会读取配置文件的内容,通过sentinel monitor master-name ip redis-port quorum
命令找到需要监控的主节点。其中master-name
是为主节点起一个名字,因为故障恢复后当前监控的系统的主节点的地址和端口会发生变化,所以哨兵通过该名字来获取当前系统的主节点的地址和端口号。
一个哨兵进程可以同时监控多个Redis主从架构的系统,只需要提供多个sentinel monitor
的配置即可。同时多个哨兵也可以同时监控一个Redis主从架构的系统。
哨兵启动后,会与要监控的主节点建立两条连接。其中一条连接是用来订阅该主节点的_sentinel_:hello
频道以获取其它同样监控该节点的哨兵节点信息,另外一条连接是向主节点发送info
等命令来获取主节点本身的信息。
当和主节点成功建立连接之后,哨兵会定时执行以下三个操作:
(1)每隔10s哨兵会向主节点和从节点发送info
命令,这样的话,哨兵就可以获取当前节点的相关信息,从而实现新节点的自动发现。前面我们也说了配置哨兵监控Redis主从系统只需要指定主节点的信息即可,是因为哨兵借助了info
命令来获取所有该主节点的从节点列表,而后和每个从节点同样建立两个链接。
(2)每隔2s哨兵会向主节点和从节点的_sentinel_:hello
频道发送自己的信息;
(3)每隔一定时间哨兵会向主节点、从节点和其它哨兵节点发送ping
命令,经过前面两个操作,哨兵此时就实现了自动发现从节点和其它哨兵节点了,此时哨兵要做的就是定时监控这些节点有没有停止服务,所以每隔一定时间会向这些节点发送ping
命令。(时间间隔与down-after-milliseconds
配置有关,当down-after-milliseconds
的值小于1s,哨兵会每隔down-after-milliseconds
指定的时间发送一次ping命令;当down-after-milliseconds
的值大于1s时,则每隔1s发送一次ping命令)
当超过down-after-milliseconds
配置的时间后,如果被ping的节点仍然没有回复,则哨兵认为其主观下线(表示当前的哨兵认为该节点已经下线)。如果该节点是Redis服务节点,则哨兵会进一步判断是否需要进行故障恢复,哨兵发送sentinel is-master-down-by-addr
命令询问其他哨兵节点是否也认为该主节点主观下线,如果达到指定数量(quorum参数)时,哨兵会认为其客观下线。并选举领头的哨兵节点对主从架构系统进行故障恢复。
3.1 领头哨兵选举步骤
故障恢复需要由领头哨兵来完成,这样就可以保证同一时间只有一个哨兵节点来执行故障恢复。选举领头哨兵的过程如下:
(1)发现主节点客观下线的哨兵节点(以下称之为A)向每个哨兵节点发送命令,要求对方选自己为领头哨兵;
(2)如果目标哨兵节点没有选过其它节点,则会同意将A设置为领头哨兵;
(3)如果A发现有超过半数且超过quorum
参数值的哨兵节点同意选自己成为领头哨兵,则A成功成为领头哨兵;
(4)当有多个哨兵节点同时参选领头哨兵,则会出现没有任何节点当选的可能。此时每个参选节点将等到一个随机时间重新发起参选请求,进行下一轮选举,直到选举成功。
3.2 故障恢复
选出领头哨兵后就要开始对主节点进行故障恢复。首先要选出一个从节点作为主节点,其挑选的过程如下:
(1)所有在线的从节点中,选择优先级最高的从节点作为主节点。优先级可以通过replica-priority
选项进行配置。
(2)如果有多个最高优先级的从节点,则复制的命令偏移量越大越有可能成为主节点。
(3)如果以上条件都一样,则选择运行ID较小的从节点。
选出一个从节点后,领头哨兵将向从节点发送slaveof no one
命令使其升级为主节点,而后领头哨兵向其它从节点发送slaveof
命令来使其成为新主节点的从节点。最后更新内部的记录,将已经停止服务的旧的主节点更新为新的主节点的从节点,当其恢复服务时以从节点的身份继续对外提供服务。