redis sentinel(哨兵)

Sentinel是redis高可用的方案,通过设立一个或多个Sentinel监视服务器,可以在主服务器下线的时候及时选举切换到从服务器,保证可用性。
Sentinel本身也是服务器,只是运行在特殊模式下,监听其他服务器而已。

Sentinel原理

sentinel 是通过定时检查主服务器和从服务器的在线状态,如果主服务器不在线,则选举一个从服务器做主。

Sentinel 监视流程

  1. 初始化服务器:Sentinel也是一个redis服务器,所以也需要初始化一个redis服务器,但是其中略有不同:sentinel无需在启动时载入持久化文件
  2. 将普通redis服务器代码替换为Sentinel专用代码:比如替换运行端口,使用sentinel特有的redisCommandTable字典
  3. 初始化Sentinel状态:将Sentinel有关的状态载入sentinelState的结构体内。sentinelState结构体有几个比较重要的属性:
    1. current_epch:当前纪元,一个计数器,用于记录故障恢复的次数和故障转移
    2. masters字典:记录所有配置中受Sentinel监视的主服务器节点,键为服务器名,值为sentinelRedisInstance结构体,这个结构体可以是从从服务器、主服务器、或者另一个Sentinel
  4. 初始化sentinelState内的master字典:该字典将通过Sentinel配置文件初始化,一个主服务器名称对应一个sentinelRedisInstance实例.sentinelRedisInstance结构体内几个重要属性:
    1. flags:整数标识值,记录实例的类型和状态
    2. name:主服务器有配置文件指定,从服务器由ip:port形成
    3. config_epoch:配置纪元,计数器,用于记录故障恢复次数和故障转移
    4. down_after_period:判断主观下线的无响应时间,单位ms,由设置down-after-milliseconds指定
    5. quorum:判断客观下线需要的投票数量
    6. slaves:从服务器字典,ip:port作为键,sentinelRedisInstance作为值
  5. 创建连接主服务器的网络连接:这时才会连接主服务器,会产生两个连接:一个命令连接,用于向主服务器发送命令和接受回复;一个订阅连接,订阅主服务器的_sentinel_:hello频道。主服务器会将自身的从服务器同步给sentinel,这样sentinel就能掌握所有从服务器信息。
  6. 获取主服务器信息:sentinel默认每10秒对主服务器发送INFO命令,主服务器返回自身和自己从服务器的信息
  7. 创建到从服务器的连接:和主服务器一样,sentinel也会对从服务器建立命令连接和订阅连接。sentinel在连接从服务器之后,也会默认10秒一次,向从服务器发送INFO命令,从服务器将它的信息返回给sentinel
  8. 向主服务器和从服务器发送信息和接受信息:通过命令连接,sentinel会向主服务器和从服务器的_sentinel_:hello发送信息,包含主服务器和sentinel自身的ip、端口、配置纪元等信息,同时sentinel也会通过订阅连接订阅_sentinel_:hello。通过这种方式,监听同一个服务器的多个sentinel将会彼此发现,并将其他的sentinel信息也保存到master字典sentinelRedisInstance值的sentinels字典内,sentinels和master一样,也是一个name-sentinelRedisInstance的字典,只是内部存放的是所有sentinel的实例
  9. 创建连接其他sentinel的命令连接:sentinel之间通信,选主投票会使用这个连接

sentinel检查下线

主观下线:

sentinel默认每秒一次,向它监视的实例(主服务器,从服务器,sentinel)发送ping命令,如果实例没有在down_after_period时间内返回响应,或者返回了PONG、LOADING、MASTERDOWN这三个响应之外的响应,则认定该实例主观下线。实例对应flags打开SRI_S_DOWN标识.需要注意的是:几个sentinel的down_after_period时间设置的也许不同,这时,几个sentinel监视的服务器主观下线的状态可能也会不同。down_after_period属性只对一个sentinel下监听的所有主服务器,从服务器和其他sentinel有效。

客观下线:

一个sentinel认为服务器下线了,是主观下线,需要多个服务器投票,超过quorum个,才会认为这个服务器真的下线了,这是客观下线。
当sentinel发现主服务器主观下线后,将向其他sentinel发送SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>命令。如果回应也认同下线,并且回应数量超过quorum,则认为主服务器客观下线,flags打开标识SRI_O_DOWN。需要注意的是,多个sentinel之间,判断客观下线的quorum可能不同,加上它们判断主观下线的时间也不同。最后sentinel判断下线,可能并不那么简单。

故障转移:

为了将下线的主服务器换下,将从服务器换上,故障转移需要完成:选举领头sentinel、选举新的主服务器,修改从服务器复制的目标到新的主服务器,将旧的主服务器变为从服务器几步操作。

选举领头sentinel:

领头sentinel将会主导后续流程。sentinel选举的规则即为Raft领头选举算法:
1. 每个认定主服务器客观下线的sentinel都有机会称为领头,它们都将发送向其他sentinel发送SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>命令。
其中如果runid不为*,而是源sentinel的runid的话,说明源sentinel要求接收方将自己设为领头sentinel。接收sentinel将会返回一条命令回复,其中leader_runid和leader_epoch记录了接收sentinel认为的领头sentinel的runid和纪元
2. 领头sentinel选举是先到先得的,最先发起命令的被接受,其后的将拒绝
3. 如果一个sentinel被半数以上的sentinel设为了领头sentinel(通过命令回复的leader_runid统计),则这个sentinel称为这一轮的领头sentinel。
4. 如果一轮选举后未有超过半数认可的sentinel,则epoch计数加1,进行下一轮选举,直至选出

故障转移

  1. 领头sentinel从 从服务器中挑选新的主服务器,对其发送命令SLAVEOF no one使其不再复制,挑选新的服务器原则是:
    1. 去掉断开或掉线的从服务器
    2. 去掉5秒内没有回复领头sentinelINFO命令的从服务器
    3. 去掉与已下线的主服务器断开超过down-after-milliseconds*10毫秒的从服务器,保证从服务器的数据较新
    4. 按从服务器优先级、从服务器的复制偏移量、从服务器的ID,选出优先级最高,复制偏移量最大(相同优先级下),id最小(复制偏移量相同下)的从服务器为新的主服务器
  2. 通知其他从服务器复制新的主服务器:向其他从服务器发送SLAVEOF命令,指向新的主服务器ip port
  3. 旧主服务器变为从服务器:当旧主服务器再次上线时,对其发送SLAVEOF命令,指向新的主服务器

猜你喜欢

转载自blog.csdn.net/lqadam/article/details/79429601