redis进阶:哨兵模式工作原理及搭建
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis进阶:哨兵模式工作原理及搭建相关的知识,希望对你有一定的参考价值。
0. 引言
上一章我们讲解了redis的主从搭建,但要实现真正的可靠的主从结构,还需要实现主从切换。也就是当主节点宕机时,从节点能够自动切换为主节点。
这就需要借助哨兵模式来实现,今天我们就来看如何搭建哨兵模式
1. 原理
1.1 哨兵的作用
所谓哨兵就是有一个放哨的,一旦发现主节点不行了,就会告诉从节点顶上。
它的核心作用有三个:
- 监控节点状态,判断主节点是否挂掉
- 当主节点挂掉时,进行主从切换,选出新的主节点
- 将选出新主的消息告诉其他节点以及客户端
所以它的原理其实就围绕这三点展开
1.2 监控节点状态
哨兵会定时发送三个任务:
(1)每10s会向主节点发送info
指令,并通过主节点来获取配置的从节点信息,也就是主从节点的网络拓扑图(结构信息)。这样当有新的从节点配置进来时可以感知到
(2)每2s广播当前哨兵对于主节点的判断(是否主观下线)以及当前哨兵节点的信息(让别的哨兵知道“我”还活着)。这里广播是通过redis的发布订阅模式来实现的。
(3)每1s会向主从节点、其他哨兵发送ping命令,也就是心跳检测,检查这些节点是否还活着。
1、从第三个任务我们可以看到,哨兵每1s会发送一个ping
命令给监控的主从节点,在规定时间内(is-master-down-after-milliseconds
)没有收到有效回复时就会认为这个节点下线
了。
但是这里会涉及一个问题,生活中我们一般认为一个人的想法是主观想法,大多数人的想法近似于客观想法。redis中也有这样一个概念,一个哨兵节点认为某个节点挂了,这是主观下线;大多数哨兵节点认为某个节点挂了,这是客观下线。这样的好处也很明显,可以减少误判。
比如说某个哨兵节点的网络刚好有波动,ping节点时没有ping通,结果就认为redis节点挂了,实际上是网络的问题。而大多数哨兵都同时出现网络问题的概念就比较低了,触发机房整体出现网络问题,那这是redis节点也自然挂了。
2、所以当一个哨兵节点认为这个主节点主观下线后,就会发送命令is-master-down-by-addr
询问其他哨兵,该节点有没有下线。
3、如果达到指定数量(quorum
,默认半数以上)的哨兵节点都认为某个主节点主观下线了, 该哨兵就会认为该主节点客观下线
了。
通过这样来监控节点的状态
1.3 哨兵的的个数
当哨兵判定某个节点为客观下线
后,就会向其他哨兵发起投票,选出一个leader哨兵,最后由这个leader哨兵来进行主从切换
所以我们一般要求哨兵节点为2个及以上,且为奇数,也就是至少3个。想想为什么?
因为如果为偶数个的哨兵节点时,就会出现"脑裂"问题,这个在es集群中也比较常见,比如一半的哨兵投了反对票, 一半的投了支持票,请问最终结果如何?
其次因为哨兵需要半数以上投票通过才能通过,当为2节点时。如果宕机了一个节点,就永远只有一个节点,则永远不能超过半数以上了,而为2节点时,即使宕机1个,还有2个节点可以投票,也能满足半数以上。
所以,我们必然需要奇数个哨兵才能真正投票出结果
1.4 哨兵的投票机制
但奇数个哨兵就万事大吉了吗?如果每个哨兵都投个自己,那不是没法选出一个leader了吗?
redis哨兵的投票算法当然想到了这点。
1、首先,最先发现主节点为客观下线的哨兵,redis将其定义为“候选者”
2、候选者会先投自己一票,可以理解为“我发现的问题,我要自己解决”
3、然后会向其他哨兵发起投票请求(请把票投给我),每个哨兵都有一票,候选者可以把票投给自己,非候选者收到投票请求后,可以选择同意或拒绝,如果收到两个候选者的投票请求,先到先得。
4、候选者会统计自己获取到的票数,直到获取的票数超过半数,且超过所配置的quorum
数,这次选举就成功了,会晋升为Leader,并且负责主从切换事宜。
1.5 哨兵主从切换
当选举出哨兵Leader后,就可以进行主从切换了。
1、从挂掉的主节点下的所有的从节点中选一个状态健康、优先级高且数据完整的从节点。
所谓状态健康就是网络连接正常的,主要是主从节点在
down-after-milliseconds
时间内产生过网络通信的即可认为是健康的从节点。而优先级高则是根据
slave-priority
配置的值来判定的数据完整则是当优先级相同,复制的数据下标越多则数据越完整(主从复制时从节点会记录复制的数据下标),如果优先级和数据完整都想同时就会选择节点ID最小的那个
这里大家可能会想:“哨兵是怎么知道主节点下有哪些从节点的,主节点不是都挂掉了吗?”
答:还记得我们上面讲的哨兵的三个定时任务吗?哨兵就是通过第一个定时任务获取的从节点信息,并且记录在册,以供使用。
2、然后通过指令slaveof no one
清除这个从节点的SLAVE信息,也就是取消掉其附属的主节点,让其成为主节点。
3、同时将挂掉的主节点的所有从节点信息再挂载到新的主节点上
4、至此,内部的主从转换就完成了,但下一步我们还需要将新主节点的信息广播给客户端。当然这里的广播是通过redis的发布/订阅模式来实现的
5、还没完,旧的主节点哨兵也会持续监听,当它恢复后,哨兵会将其作为从节点挂载到新主节点上。所以这里要注意,主节点宕机后再恢复,并不会自动再切回主节点,而是作为从节点存在。
至此,我们关于哨兵模式的原理就介绍完成了。下面我们来看具体实操。
2. 哨兵搭建
1、首先准备三个节点,一主双从,并启动。如果不知道如何搭建的,可以参考我之前的文章:
安装redis的四种方式
redis进阶:搭建redis主从架构
2、可以单独启动redis节点作为哨兵节点,也可以配置到原有的数据节点(主从节点)中,这里为了节约服务器资源,我们将哨兵配置到原来的主从节点中
3、哨兵有一个单独的配置文件sentinel.conf
,在redis的安装目录下可以看到
4、修改三个节点的配置文件
vim sentinel.conf
修改内容:
# 关闭保护模式
protected-mode no
# 哨兵监听端口,默认26379
port 26379
# 后台启动,即开启守护进程
daemonize yes
# 日志路径
logfile "/var/local/redis/logs/sentinel.log"
# 指定数据存放路径,默认/tmp
dir "/tmp"
# 监听的主节点 mymaster为主节点名称,最后的2为quorum值
sentinel monitor mymaster 192.168.244.27 6379 2
# 如果master节点有密钥要补充密码
#sentinel auth-pass mymaster xxx
# 判定服务器down掉的时间周期,默认30000毫秒(30秒)
sentinel down-after-milliseconds mymaster 30000
# 故障节点的最大超时时间为180000(180秒)
sentinel failover-timeout mymaster 180000
5、如果未关闭防火墙,需要开启哨兵监听端口
# 查询端口是否开放
firewall-cmd --query-port=26379/tcp
# 开启端口
firewall-cmd --add-port=26379/tcp --permanent
# 开启后重新加载
firewall-cmd --reload
6、启动哨兵
cd redis安装目录
redis-sentinel sentinel.conf
7、查看日志
tail -f /var/local/redis/logs/sentinel.log
8、查看哨兵是否启动
(1)通过ps指令查询
ps -ef | grep sentinel
(2)通过redis-cli连接哨兵节点,连接成功说明启动成功
3. 测试
1、关闭主节点
(1)查询进程
ps -ef | grep reids
(2)kill 主节点
kill -9 1212
2、查看哨兵日志
可以看到已经切换到从节点28服务器了
3、查看从节点信息,到新主节点上执行
redis-cli info replication
从节点已经更新为主节点了,并且其下现在只有一个从节点
4、我们再把原主节点启动起来
service redis start
# 我这里已经将启动脚本配置到/etc/init.d文件夹并命名为redis了,所以可以通过service启动,如果没有配置的,使用以下指令启动
redis-server /etc/redis/6379.conf
5、观察哨兵日志,发现原主节点被转换为从节点
6、再次观察从节点信息
新增了一个从节点,即原来的主节点,与我们上述的原理解析相符
7、我们在尝试在新节点上更新一个key
8、从节点查看该key
主从切换成功,哨兵搭建完成
4. 配置哨兵开机启动
1、之前我们已经讲解了设置redis开机自启,我们在此基础上操作
2、修改原有redis启动脚本
vim /etc/init.d/redis
脚本内容
REDISPORT=6379
# 配置哨兵端口
REDIS_SENTINEL=26379
EXEC=/var/local/redis/redis-6.2.7/src/redis-server
CLIEXEC=/var/local/redis/redis-6.2.7/src/redis-cli
# 配置哨兵执行脚本
EXEC_SENTINEL=/var/local/redis/redis-6.2.7/src/redis-sentinel
PIDFILE=/var/run/redis_$REDISPORT.pid
CONF="/etc/redis/$REDISPORT.conf"
# 哨兵配置文件路径
SENTINEL_CONF="/var/local/redis/redis-6.2.7/sentinel.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
# 启动哨兵服务
echo "Starting Redis-Sentinel server..."
$EXEC_SENTINEL $SENTINEL_CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
# 关闭哨兵服务
echo "Stoping sentinel..."
$CLIEXEC -p $REDIS_SENTINEL shutdown
while [ -x /proc/$PID ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
3、如果之前没配置过,则需要操作以下步骤,如果已经按照过我之前的配置添加过redis开机自启的则无需配置
(1)赋予文本权限
chmod 777 /etc/init.d/redis
(2)添加开机自启
chkconfig redis on
4、重启哨兵服务器,连接哨兵端口测试
redis-cli -p 26379
连接成功,说明启动成功
总结
至此,我们哨兵模式的搭建就完成了,希望大家可以借此更加深入理解redis原理,下一期,我们继续讲解redis的集群模式,实现真正的redis高可用
以上是关于redis进阶:哨兵模式工作原理及搭建的主要内容,如果未能解决你的问题,请参考以下文章
REDIS04_主从复制概述及搭建反客为主薪火相传原理哨兵模式集群搭建