Sentinel是Redis高可用性的解决方案:由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将已下线主服务器属下的模模个从服务器升级为新的主服务器,然后由新的主服务器代替已下线的主服务器继续处理命令请求。
- 启动并初始化Sentinel
-
初始化服务器
-
将普通redis服务器使用的代码替换成Sentinel专用代码
-
初始化Sentinel状态,sentinelState结构中保存了服务器中所有和Sentinel功能有关的状态:
- 当前纪元,用于实现故障转移:uint64_t current_epoch
- 所有被这个sentinel监视的主服务器:dict *masters
- 是否进入了tilt模式:int tilt
- 正在执行的脚本数量:int running_scripts
- 进入tilt模式的时间:mstime_t tilt_start_time
- 最后一次执行时间处理器的时间:mstime_t previous_time
- FIFO队列,包含了所有需要执行的用户脚本:list *scripts_queue
- 根据给定的配置文件,初始化Sentinel的监视主服务器列表(dict *masters):字典的键是被监视主服务器的名字,字典的值则是被监视主服务器对应的sentinelRedisInstance结构
- 创建连向主服务器的网络连接
- 命令连接:专门用于向主服务器发送命令,并接收命令回复
- 订阅连接:专门用于订阅主服务器的_sentinel_:hello频道
-
- 获得主服务器信息
Sentinel默认会以每10s/次的频率,通过命令连接向被监视的主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。
- 获取从服务器信息
当Sentinel发现主服务器有新的从服务器出现时,Sentinel除了会为这个新的从服务器创建相应的实例结构之外,还会创建连接到从服务器的命令连接和订阅连接。
- 向主服务器和从服务器发送信息
默认情况下,Sentinel会以2s/次的频率,通过命令连接向所有被监视的主服务和从服务器发送信息
- 接收来自主服务器和从服务器的频道信息
对于监视同一个服务器的多个Sentinel来说,一个Sentinel发送的信息会被其他Sentinel接收到,这些信息会被用于更新其他sentinel对发送信息sentinel的认知,也会被用于更新其他sentinel对被监视服务器的认知。
- 检测主观下线状态
默认情况下,sentinel会以1s/次的频率向所有与它创建了命令连接的实例(包括主服务器、从服务器、其他sentinel在内)发送PING命令,并通过实例返回的PING命令回复来判断实例是否在线。
- 检查客观下线状态
当sentinel将一个主服务器判断为主观下线之后,为了确认这个主服务器是否真的下线,他会向同样监视这一主服务器的其他Sentinel进行询问,看他们是否也任务主服务器已经下线。当Sentinel从其他sentinel那里接收到足够数量的已下线判断之后,sentinel就会将主服务器判定为客观下线,并进行故障转移操作。
- 选举领头sentinel
- 每个成为candidate的sentinel将自己纪元数+1,并向其他sentinel发送要求选举自己为局部领头sentinel的命令
- 每个folloewer-candidate都选举第一个接收到的请求作为自己的局部领头sentinel并回复,然后将自己的纪元数+1
- 每个candidate统计自己的票数,如果>=n/2+1,则该sentinel成为领头sentinel。
- 故障转移
- 在已下线主服务器属下的所有从服务器里面,挑选出一个从服务器,并将其转换为主服务器
- 让已下线主服务器属下的所有从服务器改为复制新的主服务器
- 将已下线主服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,他就会成为新的主服务器的从服务器。