深入Redis原理与应用——哨兵模式Sentinel
简介
(1)由一个或多个 Sentinel 实例组成的 Sentinel 系统可以监视任意多个主服务器及其下属的所有从服务器,当主服务器下线后自动将主服务器的某个从服务器升级称为新的主服务器。
(2)当某一主服务器 server1 下线超过用户设定的时长后,sentinel 系统就会执行故障转移操作:
- 首先会挑选 server1 属下的一个从服务器并将其升级为新的主服务器。
- 之后 sentinel 系统会向 server1 属下的所有从服务器发送新的复制指令让他们称为新的主服务器的从服务器。
- sentinel 会继续监视下线的 server1,使其上线后作为新的主服务器的从服务器。
(3)启动并初始化 sentinel:sentinel 本身可看作一个运行在特殊模式下的 redis 服务器,所以启动 sentinel 的第一步就是初始化一个普通的 redis 服务器,由于其不使用数据库也就没有载入 RDB 或 AOF 文件的过程;第二步就是将一部分普通的 redis 服务器使用的代码替换成 sentinel 专用的代码;第三步是初始化 sentinel的状态:sentinelState 结构;第四步初始化 sentinelState 的 masters 属性,其是一个字典,字典的键是被监视的主服务器的名字,字典的值是被监视的主服务器对应的 sentinelRedisInstance 结构,masters 的初始化会根据被载入的 sentinel 配置文件决定;第五步是创建连向主服务器的网络连接:每个 sentinel 会创建两个连向每个主服务器的连接,一个是命令连接一个是订阅连接。
(4)获取主服务器的信息:sentinel 会以每十秒一次的频率通过命令连接向被监视的主服务器发送 INFO 命令,通过分析回复获取主服务器的当前信息。INFO 命令的回复包括主服务器本身的信息和主服务器下属所有从服务器的信息。Sentinel 会更新主服务器的信息(已存在的更新未存在的创建),以及更新主服务器下属的从服务器的信息(主服务器信息存在masters 字典的 sentinelRedisInstance 中,而从服务器的信息都存在其中的 slaves 属性中,每个从服务器信息也是一个 sentinelRedisInstance 结构,但其 flags 不同:主SRI_MASTER 从 SRI_SLAVE,主服务器的 name 是由配置文件决定的,从服务器的 name 即 IP+端口)。
(5)获取从服务器的信息:当 sentinel 发现新的从服务器时不仅为其创建实例结构也会为其创建命令连接和订阅连接,并同样以十秒一次的频率发送 INFO 并分析回复,更新结构。
(6)向主从服务器发送信息:sentinel 会两秒一次的频率通过命令连接向主从服务器的_sentinel_:hello 频道发送包括 sentinel 自身信息、主服务器的信息(主服务器而言就是其自身的信息,从服务器而言就是它所复制的主服务器信息)。
(7)接收来自主从服务器的信息:当 sentinel 与主从服务器建立起订阅连接后,sentinel对_sentinel_:hello 频道的订阅就会一直持续到连接断开,也就是说每个 sentinel 连接的服务器,sentinel 既通过命令连接向服务器的_sentinel_:hello 频道发送消息,又通过订阅连接从服务端的_sentinel_:hello 接收消息。(一个 sentinel 通过命令连接发送的消息除了会被服务器接收到,还会通过订阅连接发送给所有监视该主服务器的 sentinel,包括
其自身)。更新 sentinel 字典:sentinel 为主服务器创建的状态结构 sentinelRedisInstance 中的 sentinels 属性保存了除当前 sentinel 外其它监视该服务器的 sentinel,其 flags 为SRI_SENTINEL。当一个 sentinel 接收到其它 sentinel 发送来的消息后就会更新这个结构。
(8)创建连向其它 sentinel 的命令连接:当 sentinel 发现一个新的 sentinel 时,它不仅会为新的 sentinel 在 sentinels 字典中创建一个示例结构,还会创建一个连向新 sentinel的命令连接,新 sentinel 也会创建一个连向此 sentinel 的命令连接(sentinel 直之间不会创建订阅连接)
检测主观客观下线状态:
(1)检测主观下线状态:sentinel 会以每秒一次的频率向所有与它创建了命令连接的实例(主服务器、从服务器、其它 sentinel)发送 PING 命令,并通过返回的 PING 命令判读是否在线。如果连续一段时间都没有得到有效的回复,sentinel 会将其标为主观下线状态(flags 属性中打开 SRI_S_DOWN 标识)。
(2)检测客观下线状态:当 sentinel 判断一个主服务器为主观下线状态后,为了确认其是否真的下线,还会向同样监视这台主服务器的其它 Sentinel 进行询问,若收到了足够数量的下线状态回应,则会将其判断为客观下线状态并对此主服务器执行故障转移操作。
(3)选举领头的 Sentinel:当一个主服务器下线后,监视这个下线主服务器的各个 sentinel会进行协商,选举出一个领头 sentinel,并由领头 sentinel 对下线的主服务器执行故障转移操作。每次进行领头 sentinel 选举之后无论是否成功都将 sentinel 的配置纪元加一;在每个配置纪元中所有的 sentinel 都有一次将某个 sentinel 设置为局部领头 sentinel 的机会且当前配置纪元中不能更改;每个发现主服务器进行客观下线的 sentinel 都会要求其它sentinel 将自己设为局部领头 sentinel;源 sentinel 接收到目标 sentinel 消息后会先检查配置纪元是否相同,若相同则查看其局部领头 sentinel 是否为自己;如果某个 sentinel被半数以上 sentinel 设置为了局部领头 sentinel 则其就会成为领头 sentinel。
故障转移,包含以下三个步骤:
(1)在已下线的服务器属下的从服务器中选出一个从服务器并将其转换为主服务器:领头 sentinel 会将已下线的服务器的所有从服务器保存到一个列表里面,然后按照以下规则一项一项进行过滤:
- 删除列表中处于下线或离线状态的从服务器。
- 删除列表中五秒内没有回复过领头 sentinel 的 INFO 命令的从服务器。
- 删除列表中与主服务器连接断开超过一定时间的从服务器。
领头 sentinel 将根据从服务器的优先级排序,选出优先级最高的,如果多个优先级相同则选用复制偏移量最大的,如何复制偏移量也相同则使用 ID 最小的。
(2)修改从服务器的复制目标
(3)待旧的主服务器上线后使其成为新的主服务器的从服务器(因为旧的已下线所以此配置信息保存在它的对应实例结构中)