参考资料更加详细,本文是笔记和个人解读,可以用来参考,也加入了哨兵的缺点
Redis Sentinel,即Redis哨兵,在Redis 2.8版本开始引入。哨兵的核心功能是主节点的自动故障转移。下面是Redis官方文档对于哨兵功能的描述:
不断地
检查主节点和从节点是否运作正常。升级为新的主节点
,并让其他从节点改为复制新的主节点
。连接哨兵(rocket的nameserver也是差不多这个流程)
来获得当前Redis服务的主节点地址。发送给客户端(主动通知)
。其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则需要在与客户端的交互中才能体现。
在前面的文章中,只要通过API访问redis服务器,都会称作客户端,包括redis-cli、Java客户端Jedis等
;为了便于区分说明,本文中的客户端并不包括redis-cli,而是比redis-cli更加复杂:redis-cli使用的是redis提供的底层接口,而客户端则对这些接口、功能进行了封装
,以便充分利用哨兵的配置提供者和通知功能
。
省略,可查阅参考资料
在故障转移阶段,哨兵和主从节点的配置文件都会被改写
主节点没有了slaveof配置(去掉了这段配置)
,其从节点则slaveof新的主节点(新增上去)
。主从节点信息的变化
,纪元(epoch)也会变化,+1。哨兵系统的搭建过程,有几点需要注意:
(1)哨兵系统中的主从节点,与普通的主从节点并没有什么区别
,故障发现和转移是由哨兵来控制和完成的(起码在配置文件中感知不到是否被哨兵监控)。
(2)哨兵节点本质上
是redis节点(但没有存储数据)。
(3)每个哨兵节点,只需要配置监控主节点,便可以自动发现其他
的哨兵节点和从节点。
(4)在哨兵节点启动和故障转移阶段,各个节点的配置文件会被重写(config rewrite)
。
(5)本章的例子中,一个哨兵只监控了一个主节点;实际上,一个哨兵可以监控多个主节点,通过配置多条sentinel monitor即可实现。
Jedis客户端对哨兵提供了很好的支持。我们只需要向Jedis提供哨兵节点集合和masterName,构造JedisSentinelPool对象;然后便可以像使用普通redis连接池一样来使用
了:通过pool.getResource()获取连接,执行具体的命令。
在整个过程中,我们的代码不需要显式的指定主节点的地址,就可以连接到主节点;代码中对故障转移没有任何体现,就可以在哨兵完成故障转移后自动的切换主节点
。之所以可以做到这一点,是因为在JedisSentinelPool的构造器中,进行了相关的工作;主要包括以下两点:
其中一个哨兵
节点+masterName获得主节点的信息;该功能是通过调用哨兵节点的sentinel get-master-addr-by-name
命令实现,该命令示例如下:开启一个单独的线程
,订阅哨兵节点的+switch-master频道,当收到消息时,重新初始化连接池
。每个哨兵节点维护了3个定时任务。定时任务的功能分别如下:通过向主从节点发送info命令获取最新的主从结构;通过发布订阅功能获取其他哨兵节点的信息;通过向其他节点发送ping命令进行心跳检测,判断是否下线。
在心跳检测的定时任务中,如果其他节点超过一定时间没有回复
,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”(即这个哨兵自己这么认为,还没有得到大部分哨兵同意
)判断下线;与主观下线相对应的是客观下线。
哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵(是主动询问其他哨兵!)
节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对该主节点进行客观下线。
需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作(因为这两个节点,也不需要故障转移;就算是判断错了,也没有影响。
)。
当主节点被判断客观下线以后,各个哨兵节点会进行协商
,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。
监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导者。选举的具体过程这里不做详细描述,一般来说,哨兵选择的过程很快,谁先完成客观下线,一般就能成为领导者。
选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:
slave-priority
指定);如果优先级无法区分,则选择复制偏移量最大(数据最新的。前一篇说过,主从复制可能会丢失部分数据)
的从节点;如果仍无法区分,则选择runid最小
的从节点。在我看来,哨兵实现了服务的高可用性。并不能保证数据的一致性,在多种场景下,都可能会出现数据丢失的现象(这点非常重要!!
)
参考:https://www.cnblogs.com/hbbbs/articles/8319921.html
与哨兵相关的几个配置。
(1) sentinel monitor {masterName} {masterIp} {masterPort} {quorum}
sentinel monitor是哨兵最核心的配置,在前文讲述部署哨兵节点时已说明,其中:masterName指定了主节点名称,masterIp和masterPort指定了主节点地址,quorum是判断主节点客观下线的哨兵数量阈值:当判定主节点下线的哨兵数量达到quorum时,对主节点进行客观下线。建议取值为哨兵数量的一半加1。
(2) sentinel down-after-milliseconds {masterName} {time}
sentinel down-after-milliseconds与主观下线的判断有关:哨兵使用ping命令
对其他节点进行心跳检测,如果其他节点超过down-after-milliseconds配置的时间没有回复
,哨兵就会将其进行主观下线。该配置对主节点、从节点和哨兵节点的主观下线判定都有效
。
down-after-milliseconds的默认值是30000,即30s;可以根据不同的网络环境和应用要求来调整:值越大,对主观下线的判定会越宽松,好处是误判的可能性小,坏处是故障发现和故障转移的时间变长,客户端等待的时间也会变长。例如,如果应用对可用性要求较高,则可以将值适当调小,当故障发生时尽快完成转移;如果网络环境相对较差,可以适当提高该阈值,避免频繁误判。
(3) sentinel parallel-syncs {masterName} {number}
sentinel parallel-syncs与故障转移之后从节点的复制有关:它规定了每次向新的主节点发起复制操作的从节点个数。例如,假设主节点切换完成之后,有3个从节点要向新的主节点发起复制;如果parallel-syncs=1,则从节点会一个一个开始复制;如果parallel-syncs=3,则3个从节点会一起开始复制。
parallel-syncs取值越大,从节点完成复制的时间越快,但是对主节点的网络负载、硬盘负载造成的压力也越大;应根据实际情况设置。例如,如果主节点的负载较低,而从节点对服务可用的要求较高,可以适量增加parallel-syncs取值。parallel-syncs的默认值是1。
(4) sentinel failover-timeout {masterName} {time}
sentinel failover-timeout与故障转移超时的判断有关,但是该参数不是用来判断整个故障转移阶段的超时,而是其几个子阶段的超时,例如如果主节点晋升从节点时间超过timeout,或从节点向新的主节点发起复制操作的时间(不包括复制数据的时间)超过timeout,都会导致故障转移超时失败。
failover-timeout的默认值是180000,即180s;如果超时,则下一次该值会变为原来的2倍