哨兵机制
1、什么是哨兵,哨兵的作用是什么?
哨兵其实就是一个运行在特殊模式下的Redis进程,主从库实例运行的同时,它也在运行。哨兵主要负责的就是三个任务:监控、选主(选择主库)和通知。
- 监控:哨兵进程在运行时,周期性地给所有的主从库发送PING命令,检测它们是否仍然在线运行。如果从库没有在规定时间内响应哨兵的PING命令,哨兵就会把它标记为“下线状态”;同样,如果主库也没有在规定时间内响应哨兵的PING命令,哨兵就会判定主库下线,然后开始自动切换主库的流程。
- 选主:主库挂了以后,哨兵就需要从很多个从库里,按照一定的规则选择一个从库实例,把它作为新的主库。这一步完成后,现在的集群里就有了新主库。
- 通知:在执行通知任务时,哨兵会把新主库的连接信息发给其他从库,让它们执行replicaof命令,和新主库建立连接,并进行数据复制。同时,哨兵会把新主库的连接信息通知给客户端,让它们把请求操作发到新主库上。
总结:Redis的哨兵机制自动完成了以下三大功能,从而实现了主从库的自动切换,可以降低Redis集群的运维开销:
- 监控主库运行状态,并判断主库是否客观下线;
- 在主库客观下线后,选取新主库;
- 选出新主库后,通知从库和客户端。
2、哨兵如何判断主库的下线状态?
哨兵对主库的下线判断有“主观下线”和“客观下线”两种。
主观下线: 哨兵进程会使用PING命令检测它自己和主、从库的网络连接情况,用来判断实例的状态。
- 如果主从库对PING命令响应超时了,哨兵就会先把它标记为“主观下线”。
- 如果检测的是从库,直接简单的标记为“主观下线”。
- 如果检测的是主库,为了防止误判,不能简单地把它标记为“主观下线“。(通过哨兵集群,少数服从多数)
客观下线: 当有N个哨兵实例时,最好要有N/2 + 1个实例判断主库为“主观下线”,才能最终判定主库为“客观下线”。
3、如何选定新主库?
哨兵选择新主库的过程称为“筛选+打分”:
- 筛选:在多个从库中,先按照一定的筛选条件,把不符合条件的从库去掉。
- 检查从库的当前在线状态,并判断它之前的网络连接状态,如果从库总是和主库断连,而且断连次数超出了一定的阈值,我们就可以认为这个从库的网络状况并不是太好,就可以把这个从库筛掉了。
- 打分:按照下述三个规则依次进行三轮打分,只要在某一轮中,有从库得分最高,那么它就是主库了。
- 第一轮:优先级最高的从库得分高。 (手动设置从库的优先级,比如给内存大的实例设置高优先级)
- 第二轮:和旧主库同步程度最接近的从库得分高。(从库的slave_repl_offset越接近主库的master_repl_offset,同步程度越高)
- 第三轮:ID号小的从库得分高。(在优先级和复制进度都相同的情况下,ID号最小的从库得分最高,会被选为新主库。)
总结: 首先,哨兵会按照在线状态、网络状态,筛选过滤掉一部分不符合要求的从库,然后,依次按照优先级、复制进度、ID号大小再对剩余的从库进行打分,只要有得分最高的从库出现,就把它选为新主库。
哨兵集群
1、哨兵实例在运行时发生了故障,主从库还能正常切换吗?
实际上,一旦多个实例组成了哨兵集群,即使有哨兵实例出现故障挂掉了,其他哨兵还能继续协作完成主从库切换的工作,包括判定主库是不是处于下线状态,选择新主库,以及通知从库和客户端。
2、基于pub/sub机制的哨兵集群组成
- 哨兵实例之间可以相互发现,要归功于Redis提供的pub/sub机制,也就是发布/订阅机制。
- 哨兵只要和主库建立起了连接,就可以在主库上发布消息了,比如说发布它自己的连接信息(IP和端口)。同时,它也可以从主库上订阅消息,获得其他哨兵发布的连接信息。
- 当多个哨兵实例都在主库上做了发布和订阅操作后,它们之间就能知道彼此的IP地址和端口。
- 除了哨兵实例,我们自己编写的应用程序也可以通过Redis进行消息的发布和订阅。
- 为了区分不同应用的消息,Redis会以频道的形式,对这些消息进行分门别类的管理。
- 频道,实际上就是消息的类别。当消息类别相同时,它们就属于同一个频道。反之,就属于不同的频道。
- 只有订阅了同一个频道的应用,才能通过发布的消息进行信息交换。
示例:
- 哨兵1把自己的IP(172.16.19.3)和端口(26579)发布到“__sentinel__:hello”频道上,哨兵2和3订阅了该频道。那么此时,哨兵2和3就可以从这个频道直接获取哨兵1的IP地址和端口号。
- 然后,哨兵2、3可以和哨兵1建立网络连接。通过这个方式,哨兵2和3也可以建立网络连接,这样一来,哨兵集群就形成了。
- 它们相互间可以通过网络连接进行通信,比如说对主库有没有下线这件事儿进行判断和协商。
3、哨兵如何和从库建立连接?
哨兵为什么需要和从库建立连接?
这是因为,在哨兵的监控任务中,它需要对主从库都进行心跳判断,而且在主从库切换完成后,它还需要通知从库,让它们和新主库进行同步。
哨兵是如何知道从库的IP地址和端口的呢?
- 这是由哨兵向主库发送INFO命令来完成的。
示例:
- 哨兵2给主库发送INFO命令,主库接受到这个命令后,就会把从库列表返回给哨兵。
- 接着,哨兵就可以根据从库列表中的连接信息,和每个从库建立连接,并在这个连接上持续地对从库进行监控。
- 哨兵1和3可以通过相同的方法和从库建立连接。
4、哨兵是否需要和客户端建立连接?
需要,这是因为:
- 主从库切换后,客户端也需要知道新主库的连接信息,才能向新主库发送请求操作。所以,哨兵还需要完成把新主库的信息告诉客户端这个任务。
- 在实际使用哨兵时,客户端需要通过监控了解哨兵进行主从切换的过程。 比如说,主从切换进行到哪一步了?这其实就是要求,客户端能够获取到哨兵集群在监控、选主、切换这个过程中发生的各种事件。
5、基于pub/sub机制的客户端事件通知
客户端事件通知:
- 从本质上说,哨兵就是一个运行在特定模式下的Redis实例,只不过它并不服务请求操作,只是完成监控、选主和通知的任务。
- 每个哨兵实例也提供pub/sub机制,客户端可以从哨兵订阅消息。哨兵提供的消息订阅频道有很多,不同频道包含了主从库切换过程中的不同关键事件。
具体操作:
- 客户端读取哨兵的配置文件后,可以获得哨兵的地址和端口,和哨兵建立网络连接。
- 然后,我们可以在客户端执行订阅命令,来获取不同的事件消息。