当不使用集群时哨兵会提供一个高可用redis
前面复制讲了复制机制中如果主机宕机了就无法进行写操作了。所以引入了哨兵
哨兵巡查监控后台master主机是否故障,如果故障了根据投票数自动将某一个从库转换为新主库,继续对外服务。俗称无人值守运维
监听 redis 运行状态,包括 master 和 slave
8.1 作用
主从监控
监控主从 redis 库运行是否正常
消息通知
哨兵可以将故障转移的结果发送给客户端
故障转移
如果 master 异常,则会进行主从切换,将其中一个 slave 作为新的 master
配置中心
客户端通过连接哨兵来获得当前 redis 服务的主节点地址
8.2 实例
3 个哨兵,防止一个哨兵挂了就完了。自动监控和维护集群,不存放数据,只是吹哨人
1 主 2 从,用于数据读取和存放
3 个哨兵,应该是除了 1主2从 外新建 3 个虚拟机,作为 3 个哨兵,但是 16G 内存 3个虚拟机都有点不卡,所以将这 3 个哨兵放在主机上了
哨兵的配置是在 sentinel.conf 文件中,可以理解 redis 和 sentinel 是两个独立的东西,分别由不同的配置文件进行控制,可以打开看一下里面的内容。我们把三个哨兵的配置文件都放在主机中
8.2.1 配置文件说明
里面的配置文件和 redis.conf 差不多
bind
:服务监听地址,用于客户端连接,默认本机地址
daemonize
:是否以后台 daemon 方式运行
protected-mode
:安全保护模式
port
:端口
logfile
:日志文件路径
pidfile
:pid 文件路径
dir
:工作目录
sentinel monitor <master-name> <ip> <redis-port> <quorum>
:设置要监控的 master 服务器,quorum
表示最少有几个哨兵认可客观下线,同意故障迁移的法定票数(即有 quorum 哨兵都认为 master 宕机了才进行后续操作)
因为网络是不可靠的,有时候一个 sentinel 会因为网络堵塞而误以为一个 master redis 已经宕机了,在 sentinel 集群环境下需要多个 sentinel 互相沟通来确认某个 master 是否真的宕机了,quorum 这个参数是进行客观下线的一个依据,意思是至少有 quorum 个 sentinel 认为这个 master 有故障,才会对这个 master 进行下线以及故障转移。因为有的时候,某个 sentinel 节点可能因为自身网络原因,导致无法连接 master,而此时 master 并没有出现故障,所以,这就需要多个 sentinel 都一致认为该 master 有问题,才可以进行下一步操作,这就保证了公平性和高可用。
sentinel auth-pass <master-name> <password>
:master 设置了密码,连接 master 服务的密码
还有五个,第一个后面会再讲,后面四个通常用默认的
sentinel down-after-milliseconds <master-name> <milliseconds>
:指定多少毫秒后,主节点没有应答哨兵,此时哨兵主观上认为主节点下线
sentinel parallel-syncs <master-name> <nums>
:表示允许并行同步的 slave 个数,当 master 挂了后,哨兵会选出新的 master,此时,剩余的 slave 会向新的 master 发起同步数据
sentinel failover-timeout <master-name> <milliseconds>
:故障转移的超时时间,进行故障转移时,如果超过设置的毫秒,表示故障转移失败。即虽然选举成功了,但是故障转移超时了
sentinel notification-script <master-name> <script-path>
:配置当某一事件发生时所需要执行的脚本
sentinel client-reconfig-script <master-name> <script-path>
:客户端重新配置主节点参数脚本
将哨兵配置文件复制 3 份保存到主机目录下
然后编写配置文件中的内容
基本每个配置文件都如下,就端口号不一样,port,logfile,pidfile 三个不同,三个的 sentinel monitor 和 sentinel auth-pass
都一样
bind 0.0.0.0
daemonize yes
protected-mode no
port 26379
logfile "/home/liu/redis-7.4.0/sentinel26379.log"
pidfile "/var/run/redis-sentinel26379.pid"
dir /home/liu/redis-7.4.0
sentinel monitor mymaster 192.168.153.129 6379 2 # 主机IP+端口号
sentinel auth-pass mymaster redis # 主机密码
之后按序把咱们的一主二从三个虚拟机打开,注意,这里主机的配置文件要修改一下
是不是有疑问,为什么主机也要设置 masterauth,它不是作为主机连接从机时才需要吗?
是的,确实是这样,但是由于哨兵的存在,当主机宕机后,它可能会变为从机,如果不设置 masterauth
,它将无法连接到新的主机上,后续可能报错 master_link_status:down
8.2.2 开启哨兵
使用命令
redis-sentinel sentinel26379.conf --sentinel
启动三个哨兵配置文件
之后再测试主从复制,发现没有问题
查看端口使用情况,三个哨兵全部在运行
查看一下26379的哨兵的日志文件
有三个 Sentinel ID,表示三个哨兵,monitor 和两个 slave 表示了一主二从
那再看一下26380的日志问卷
????发现其实哨兵记录的内容都是一样的,为什么?
因为正常情况下,一个哨兵位于一台服务器上,三个哨兵就应该有3台,当一个哨兵意外挂了的时候,也不会出现太大问题,哨兵机制仍可以正常使用,这也要求任何一个哨兵记录的内容都要是完整的。
????然后我们注意一下日志中有一行 Sentinel new configuration saved on disk
,这是什么呢,这里修改的是哨兵的配置文件
sentinel26379.config
sentinel26380.config
这里的 known-replica
是对于哨兵监控的 master 中的从机信息
known-sentinel
记录了除自身的哨兵ID,其他的一块进行监控的所有哨兵ID。来知道哪些哨兵是一伙的
8.2.3 测试哨兵
我们手动 shutdown
关闭 6379 主机,模拟 master 宕机,可以发现它关机时间比较久,0.87s
然后我们在另外两台机器测试还能否读取数据
都是第一次不行,第二次才可以,而且出错的原因不一样。
解释:这两个错误本质上是同一个,是因为 master 宕机,它的读/写管道关闭了,客户端读取超时而关闭了连接,,,类似地,不懂,反正你记住出现这个问题是正常的,重新发送命令就可以了
???? master 更换
6380 变为主机,6381 变为从机
我们可以看一下 log 日志文件看一下
从中我们可以看出,6380变为新master,6379,6381变为从机。也就是说即使 6379 回归,也是从机,不再是主机了。
???? 你把所有有关哨兵的配置文件、日志都删除后,发现即使所有的 redis 服务器重启,它们的主从关系还是哨兵修改后的
是因为它修改了 redis.conf 配置文件(加在配置文件末尾),我们先来看一下 redis6379 配置文件
拜了新的老大,再看 redis6380 配置文件,文件末尾是没有什么的
但是我们原来6380作为从机是配置了 replicaof
的
可以看到已经被删除了
结论
- 文件的内容,在运行期间会被 sentinel 动态进行更改
- master-slave 切换后,master_redis.conf、slave_redis.conf 和 sentinel.conf 的内容都会发生改变,master_redis.conf 会多一行 slaveof 的配置,sentinel.conf 的监控目标会随之调换
???? 注意
- 哨兵只负责监控,业务压力不大
- 生产上都是一个哨兵放在一台服务器上,很少出现所有哨兵全部挂掉的情况
- 一套哨兵可以同时监控多个 master
只需要在配置文件中,把要监控的对象再加一份即可,注意换换名字,这里是 mymaster 和 resque 两个要监控的 master
8.3 运行流程
当一个主从配置中的 master 失效之后,sentinel 可以选举出一个新的 master 用于自动接替原 master 的工作,主从配置中的其他 redis 服务器自动指向新的 master 同步数据。一般建议 sentinel 采取奇数台,防止某一台 sentinel 无法连接到 master 导致误切换。
1. 三个哨兵监控一主二从,正常运行中
2. SDOWN:主观下线
-
是单个 sentinel 自己主观上检测到的关于 master 的状态。在 sentinel 的角度来看,如果发送了 PING 心跳包后,在一定时间内没有收到合法的回复,就达到了 SDOWN 的条件。那么这个 sentinel 单方面认为这个 master 不可用了
-
sentinel 配置文件中的
down-after-milliseconds
设置了判断主观下线的时间长度# 默认是 30s sentinel down-after-milliseconds mymaster 30000
3. ODOWN:客观下线
- ODOWN 需要一定数量的 sentinel,多个哨兵达成一致意见才能认为一个 master 客观上已经宕掉
-
quorum
就是客观下线的一个依据。意思是至少有quorum
个sentinel
认为这个 master 有故障才会对这个 master 进行下线以及故障转移。因为有的时候,某个 sentinel 节点可能因为自身网络原因导致无法连接 master,而此时 master 并没有出现故障,所以这就需要多个 sentinel 都一致认为该 master 有问题,才可以进行下一步操作,这就保证了公平性和高可用
4. 选举出领导者哨兵
当主节点被判断客观下线后,各个哨兵节点会进行协商,先选举出一个领导者哨兵节点(兵王)并由该领导者节点也即被选举出的兵王进行 failover (故障迁移) 即下面的 vote-for-leader
由一个 leader 去推动整个故障迁移即可。
❓ 怎么选出来的呢?
Raft 算法,这里简单介绍一下:监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法,基本思路是先到先得,即在一轮选举中,哨兵A向B发送称为领导者的申请,如果B没有同意过其他哨兵,则会同意A称为领导者
5. 由兵王推动故障切换流程并选出一个新 master
???? 选举新王
在剩余健康的 slave 节点中进行选举
- 优先级高的作为新 master,若优先级相同,进入第二步
即redis.conf
文件中,优先级slave-priority
/replica-priority
最高的从节点 (值越小优先级越高),默认值为 100。slave-priority
是 redis5.0之前用的,之后更名为replica-priority
- 复制偏移位置 offset 最大的从节点作为新的 master,若相同,进入下一步
因为偏移量越大,说明数据越新 - 最小的 Run ID 的从节点作为新的 master。字典顺序,ASCII 码
???? 群臣俯首
执行 slaveof no one
命令让选出来的从节点成为新的主节点,并通过 slaveof
命令让其他节点成为其从节点
- Sentinel leader 会对选举出的新 master 执行
slaveof no one
操作,将其提升为 master 节点 - Sentinel leader 向其他 slave 发送命令,让剩余的 slave 成为新的 master 节点的 slave
???? 旧主拜服
将之前已下线的老 master 设置为新选出的新 master 的从节点,当老 master 重新上线后,它会成为新 master 的从节点。Sentinel leader 会让原来的 master 降级为 slave 并恢复正常工作。
总结
上述的 failover 操作均由 sentinel 自己独自完成,完全不需要人工干预
8.4 使用建议
- 哨兵节点的数量应为多个,哨兵本身应该集群,保证高可用
- 哨兵节点的数量应该是奇数
- 各个哨兵节点的配置应一致(内存、硬件配置之类的相同)
- 如果哨兵节点部署在 Docker 等容器里面,尤其要注意端口的正确映射
- 哨兵集群+主从复制,并不能保证数据零丢失
解释第5点,当 master 主机挂掉后,在选举新的 master 过程中,有大约 5~10s 是不能进行写入操作的,会有数据流失。所以推荐使用下一节的集群,redis 官方也这么说(经典白学)