Sentinel是Redis的高可用性解决方案,由一个或多个Sentinel实例组成Sentinel系统,可以用来监视任意多个主服务器和主服务器下的所有从服务器,当监视到主服务器下线之后会自动将下线主服务器下的从服务器升级为新的主服务器,由新主服务器代替已下线主服务器处理命令请求。
Sentinel是一个特殊的Redis服务器实例,Redis由一个或多个Sentinel实例构成Sentinel系统,Sentinel可以用来监测任意多个主服务器和从服务器,当Sentinel由于故障下线之后,Sentinel会进行故障转移,推选出新的主服务器。
启动Sentinel实例
可以通过下列命令启动Sentinel实例:
redis-sentinel /path/to/your/sentinel.conf
或者:
redis-server /path/to/your/sentinel.conf --sentinel
sentinel.conf配置文件示例:
sentinel monitor master1 127.0.0.1 6379 2
sentinel down-after-milliseconds master1 30000
sentinel parallel-syncs master1 1
sentinel failover-timeout master1 900000
Sentinel服务器和普通的Redis服务器使用的命令不一样,Sentinel不使用数据库所以不能使用SET等跟数据库有关的命令,在初始化时也不用载入RDB或AOF文件。
数据结构
Redis中通过sentinelState结构维护Sentinel相关的状态,其中有一个master字典维护被监视的主服务器,字典key是主服务器名称,value为一个sentinelRedisInstance结构。
Sentinel和普通服务器会建立两个连接,一个用来发送普通命令,一个用来订阅频道,用来订阅服务器的_sentinel_:hello频道,Sentinel会发布信息到该频道,在建立订阅连接之后会向服务器发送SUBSCRIBE _sentinel_:hello命令同时也订阅该频道的信息,当主服务器被多个Sentinel监视时,Sentinel可以通过该频道自动发现其它监视同一台主服务器的Sentinel,并把它添加到sentinelRedisInstance结构的sentinels属性中,并且和新发现的sentinel建立命令连接(不会创建订阅连接)。
Sentinel以默认十秒一次的频率,通过命令连接向主服务器发送INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。当主服务器接收到INFO命令时会向Sentinel回复当前主服务器的runid、以及该主服务器下所有从服务器的ip和端口并把这些从服务器信息保存到主服务器对应的sentinelRedisInstance结构的slaves属性对应的字典中。
当Sentinel发现了主服务器的新从服务器时会和从服务器建立命令连接和订阅连接,并且发送INFO命令向从服务器获取从服务器的runid、主服务器的ip端口、主从服务器连接状态、主服务器优先级、从服务器复制偏移量。并发这些信息保存到sentinelRedisInstance结构中。
节点通信
默认情况下,Sentinel每两秒一次的频率通过命令连接向所有被监视的主从服务器发送一下格式的命令:
PUBLISH _sentinel_:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"
该命令向_sentinel_:hello频道发送了一条消息,把Sentinel ip、Sentinel端口、Sentinel运行id、Sentinel当前配置纪元、主服务器 ip、主服务器端口、主服务器运行id、主服务器当前配置纪元发送到_sentinel_:hello频道,因为所有的Sentinel实例都订阅了_sentinel_:hello频道,所以这条发布消息会被所有的Sentinel实例收到,所有各个Sentinel可以通过这条订阅消息实现自动发现,并把新发现的Sentinel添加到sentinelRedisInstance结构的sentinels属性中。
Sentinel以每秒一次的频率向所有与它创建了命令连接的实例(包括主从服务器、Sentinel服务器)发送PING命令,根据PING的回复来判断实例是否在线,回复+PONG、-LOADING、-MASTERDOWN三种的一种说明在线,否则说明不在线,Sentinel配置了down-after-milliseconds选项,当连续down-after-milliseconds毫秒内都没有回复有效回复,那么Sentinel会把该实例标识为主观下线,把sentinelRedisInstance结构中的flags置成SRI_S_DOWN。
当Sentinel将一个主服务器标识为主观下线后,通过发送SENTINEL is-master-down-by-addr <ip> <port> <curent_epoch> <runid>向其它sentinel询问该主服务器是否下线,当收到足够多的下线判断之后,会把该主服务器标识成客观下线,把flags置成SRI_O_DOWN。主服务器被标识成客观下线之后,各个Sentinel实例会进行协商,推举出一个领头Sentinel,对下线的主服务器进行故障转移,推举出新的主服务器,并且更改相关从服务器的复制目标,如果旧主服务器重新上线,把它变成从服务器。
推举领头Sentinel采用了Raft算法。