可用性保证之Sentinel
Sentinel 原理
怎么实现高可用呢?第一个对于服务端来说,能够实现主从自动切换;第二个,对于客户端来说,如果发生了主从切换,它需要获取最新的master节点。
这个怎么实现呢?这里面应该要有—个管理Redis节点存活状态的角色,而且具备路由功能。
思路: 创建一台监控服务器来监控所有Redis服务节点的状态,比如,master节点超过一定时间没有给监控服务器发送心跳报文,就把master标记为下线,然后把某一个slave变成master。应用每一次都是从这个监控服务器拿到master的地址。
问题是:如果监控服务器本身出问题了怎么办?那我们就拿不到master的地址了,应用也没有办法访问。
Redis的高可用是通过哨兵Sentinel来保证的。它的思路就是通过运行监控服务器来保证服务的可用性。
从Redis2.8版本起,提供了一个稳定版本的Sentinel (哨兵),用来解决高可用的问题。
我们会启动奇数个的Sentinel的服务(通过src/redis-sentinel)。可以用sentinel的脚本启动,也可以用redis-server的脚本加sentinel参数启动:
./redis-sentinel ../sentinel.conf
或者:
./redis-server ../sentinel.conf --sentinel
它本质上只是一个运行在特殊模式之下的Redis。Sentinel通过info命令得到被监听Redis机器的master, slave等信息。
为了保证监控服务器的可用性,我们会对Sentinel做集群的部署。Sentinel既监控 所有的Redis服务,Sentinel之间也相互监控。
注意:Sentinel本身没有主从之分,地位是平等的,只有Redis服务节点有主从之分。
这里就有个问题了,Sentinel唯一的联系,就是他们监控相同的master,那其中一个Sentinel节点是怎么知道其他的Sentinle节点存在的呢?
因为Sentinel是一个特殊状态的Redis节点,它也有发布订阅的功能。
哨兵上线时,给所有的Reids节点(master/slave)的名字为_sentinel_:hello的 channle发送消息。
每个哨兵都订阅了所有Reids节点名字为_sentinel_:hello的channle,所以能互相感知对方的存在,而进行监控。
Sentinel和Sentinel集群是怎么运行的我们知道了,下面来看看它是怎么干活的。 它最大的作用就是管理Redis节点服务状态,还有切换主从。
服务下线
Sentinel是怎么知道master节点挂了?
Sentinel默认以每秒钟1次的频率向Redis服务节点发送PING命令。如果在指定时间内没有收到有效回复,Sentinel会将该服务器标记为下线(主观下线)。
由这个参数控制:
# sentinel.conf
sentinel down-after-milliseconds <master-name> <milliseconds>
默认是30秒。
但是,只有你发现master下线,并不代表master真的下线了。也有可能是你自己的网络出问题了。所以,这个时候第一个发现master下线的Sentinel节点会继续询问其他的Sentinel节点,确认这个节点是否下线,如果多数Sentinel节点都认为master 下线,master才真正确认被下线(客观下线)。
确定master下线之后,就需要重新选举master。
那么选举这件事情谁来做呢? Redis节点自己选举?还是谁?
Redis的选举和故障转移都是由Sentinel完成的。问题又来了,既然有这么多的 Sentinel节点,由谁来做故障转移的事情呢?
故障转移流程的第一步就是在Sentinel集群选择一个Leader,由Leader完成故障转移流程。Sentinle通过Raft算法,实现Sentinel选举。
Sentinle的Raft算法和Raft论文略有不同
1、master客观下线触发选举,而不是过了 election timeout时间开始选举。
2、Leader并不会把自己成为Leader的消息发给其他Sentinel。其他Sentinel等待Leader从slave选岀master后,检测到新的master正常工作后,就会去掉客观下线的标识,从而不需要进入故障转移流程。
故障转移
Redis的master节点的选举规则又是什么样的呢?
对于所有的slave节点,一共有四个因素影响选举的结果,分别是断开连接时长、优先级排序、复制数量、进程id。
1、如果与哨兵连接断开的比较久,超过了某个阈值,就直接失去了选举权。
2、如果拥有选举权,那就看谁的优先级高,这个在配置文件里可以设置 (replica-priority 100),数值越小优先级越高。
3、如果优先级相同,就看谁从master中复制的数据最多(复制偏移量最大),选最多的那个。
4、如果复制数量也相同,就选择进程id最小的那个。
master节点确定之后,又怎么让其他的节点变成它的从节点呢?
1、选出 Sentinel Leader 之后,由 Sentinel Leader 向某个节点发送 slaveof no one 命令,让它成为独立节点。
2、然后向其他节点发送slaveof x.x.x.x xxxx (本机IP端口),让它们成为这个节点的从节点,故障转移完成。
Sentinel的功能总结
监控:Sentinel会不断检查主服务器和从服务器是否正常运行。
通知:如果某一个被监控的实例岀现问题,Sentinel可以通过API发岀通知。
自动故障转移(failover):如果主服务器发生故障,Sentinel可以启动故障转移过程。把某台服务器升级为主服务器,并发出通知。
配置管理:客户端连接到Sentinel,获取当前的Redis主服务器的地址。