Sentinel(哨岗,哨兵),是Redis的高可用解决方案:
  • 由一个或多个Sentinel实例组成的Sentinel系统,
  • 可以监视任意多个主服务器,以及这些主库下面的从库
  • 并在主库掉线之后,自动选择某个从库作为新的主库。
 
说到底,就是探活,主从切换==高可用
 

 

启动并初始化Sentinel

 
redis-sentinel /path/to/your/sentinel.conf
redis-server /path/to/your/sentinel.conf --sentinel
 
当启动一个sentinel时,它需要执行以下步骤
  • 初始化服务器
  • 将普通Redis服务器使用的代码替换成Sentinel 专用代码
  • 初始化Sentinel状态
  • 根据给定的配置文件,初始化Sentinel的监控主服务器列表
  • 创建连向主服务器的网络连接
 
初始化服务器
 
sentinel 实际上是redis的一种特殊形式,因此大体初始化和redis初始化相似
不同点
  • 普通服务器初始化时会载入RDB文件或AOF文件来还原数据库状态
  • sentinel 并不使用数据库,初始化Sentinel时不会载入RDB文件或AOF文件

 

使用sentinel专用代码
 
不同点
  • 端口号
    • redis常用端口号         6379
    • sentinel常用端口号    26379
  • 命令表
    • redis--redisCommandTable
      • 如 set,get,script 等等键值对命令
    • sentinel --sentinelcmds
      • 仅包含7个命令
        • ping,sentinel,info,
        • subscribe,unsubscribe,psubscribe,punsubscribe
 
初始化sentinel状态的masters属性
 
sentinel状态中masters字典记录了所有被Sentinel监视的主服务器的相关信息;
  • 字典的键是被监视主服务器的名字
  • 字典的值则是被监视主服务器对应的 结构
    • 实例结构的属性有很多
 
创建连向主服务器的网络连接
 
创建连向被监视主服务器的网络连接,Sentinel将成为主服务器的客户端,它可以向主服务器发送命令,并从命名回复中获取相关信息。
 
对于每个被sentinel监视的主服务器来说,sentinel会创建两个连向主服务器的异步网络连接:
  • 命令连接
    • 专门用于向主库发送命令,接收命令回复。
  • 订阅连接
    • 专门用于订阅主库的__sentinel__:hello频道
 
为啥又两个连接?
  • 在Redis目前的发布与订阅功能中,被发送的信息都不会保存在redis服务器里面。
  • 如果在发送信息时,想要接收信息的客户端不在线或者断线,那么这个客户端就会丢失这条信息。
  • 因此,为了不丢失__sentinel__:hello 频道的任何信息,Sentinel必须专门用一个专门连接 接收频道信息

 

 
 
获取主服务器信息

sentinel 默认每十秒,向被监视的主库发送一次INFO命令
并通过分析INFO命令的回复来获取主库的当前信息。
 

 

主库回复INFO命令,内容
  • 主库本身信息
    • run_id,role域记录的服务器角色
  • 主库下面所有从库信息
    • slave的id,ip,port,state,offset,lag 等等信息。
 
sentinel 将主信息存在master字典中,将从信息存在Slave字典中;
 
获取新增从库信息

 
当sentinel 发现主库有新从库出现时,会为这个新从库创建相应的实例结构
并创建连接到从库,命令连接和订阅连接。
 

 

 
这样sentinel,也会每个10秒 给从库发送INFO,命令并解析其返回的内容。
 
也就是说无论主库还是从库,sentinel都会定期去取他们的信息,来分析,并做动作。
 
 
sentinel与主从间的通信

 
对于监视同一个服务器的多个sentinel来说,一个sentinel发送的信息会被其他sentinel接收到
,这些信息会被用于更新其他sentinel。
 
 
三个监视器共同监视同一主服务器

 

使用命令连接相连的各个sentinel 可以通过向其他sentinel发送命令请求来进行信息交换。
 

 

检测主观下线状态

默认情况下,sentinel 会以每秒一次的频率向所有与他创建了命令连接的实例
包含 主库,从库,其他sentinel 在内 发送ping 命令,并通过实例返回的ping命令回复 来判断实例是否在线。
 
sentinel 向实例发送ping 命令。

 

 
有效回复:
  • +PONG,-LOADING,-MASTERRDOWN
 
如果ping 命令 没有 得到上面的有效回复 则 主观下线 实例
或者是 在 down-after-milliseconds 后还没收到任何回复 也选择主观下线。
 
检查客观下线状态

  • 当sentinel 将一个主服务器判断为 主观下线之后,为了确认是否真的下线了。
  • 它会向同样监视着以主服务器的其他sentinel 进行询问,
    • 看它们是否也认为主服务器已经进入下线状态(可以是主观下线或客观下线)。当sentinel 从其他
  • sentinel 接收到足够数量的已下线判断后,sentinel 就会将主服务器判定为客观下线,并执行故障转移操作
 
使用命令,判断主库是否真下线
sentinel is-master-down-by-addr <ip> <port> <current_epoch> <runid>
 
current_epoch: sentinel 当前的配置纪元,用于选举领头sentinel;
 
 
当其他sentinel接收到 is-master-down-by-addr 后返回 三个参数
  • <down_state>
    • 1 主库已下线,0 主库未下线
  • <leader_runid>
      • 仅用于检测主库下线的标志
    • 局部领头sentinel 的运行ID
      • 用于选举领头sentinel ID
  • <leader_epoch>
    • 局部领头sentinel 的配置纪元
      • 用于选举领头sentinel
      • 仅在<leader_runid>不为* 时有效,为* 时,其值始终为0
 
 
选举领头sentinel

  • 当主库被判断为客观下线时,监视这个主库的各个sentinel 会进行协商,
  • 选出一个领头sentinel,并由其来执行对下线主库的故障转移
 
 
Redis 选举领头Sentinel 的规则
  • 所有在线Sentinel 都有被选为领头Sentinel的资格
  • 每次进行领头Sentinel选举后,无论是否成功,所有sentinel 的配置纪元(configuration epoch) 自增一次
    • 配置纪元实际就是一个计数器,没有特殊作用
  • 所有sentinel 只能选择一个 sentinel 作为领头,并且局部领头 sentinel 一旦设置,在这个配置纪元就不能修改
 
方法
  • 每个发现主库进行客观下线的sentinel都会要求设置它自己为领头
  • 当发送命令中runid 不是* 而是源sentinel 本身的 id,
    • 则要求其他sentinel将其本身设置为领头
  • 目标sentinel设置领头 规则是先到先得
    • sentinel一旦设置某为领头,则其余的要求都会被拒绝
    • 设置的方法,就是命令的回复
      • leader_runid 和 leader_epoch
  • 源sentinel接收到回复之后
    • 检查回复中的leader_epoch,leader_runid 是否 符合本身的current_epoch ,runid
    • 如相同则表示 其已被设置为领头
  • 如某个Sentinel 被半数以上的Sentinel 设置为局部领头,那么此Sentinel 成为领头Sentinel。
  • 因领头Sentinel 需要得到半数以上的支持,且每个Sentinel在每个配置纪元中,只有一次投票权
    • 所以 在每个配置纪元中,只会出现一个领头Sentinel。
  • 如果在规定时间内,没有选出领头,则各个Sentinel将在一段时间后再次选举,直到选出领头Sentinel为止。
 
故障转移

领头sentinel将对已下线的主库执行故障转移
  1. 在所有从库中,选出一个从库作为新的主库
  2. 将所有剩下的从库改为复制新的主库
  3. 将源主库设置为新的主库的从库
    • 这个源主库重新上线时,它会成为新主库的从库
 
选出新的主库
挑选一个状态良好,数据完整的从库,然后这个从库,执行
slaveof no one 
将从库转变为主库。
 
新主库如何挑选规则
  1. 删除所有处于下线或断线的从库,保证剩余从库都是正常在线
  2. 删除最近5秒没有回复过领头sentinel的INFO命令的从库
    • 保证剩余从库都是最近成功通信过的
  3. 删除所有与源主库连接断开超过 down-after-milliseconds*10 的从库
    • 保证剩余从库保存的数据都是较新的
  4. 领头sentinel根据从库的优先级,进行排序,选择优先级最高的从库
 

 

 

 

 
 
 
总结

  • sentinel 是一个特殊模式下的redis服务器。
    • 使用了不同的命令表;
  • sentinel 读取配置文件
    • 为每个主库创建实例结构,并创建连接
  • sentinel 默认每十秒 发送INFO命令 检测服务器是否在线 
  • 对于监视同一服务器的多个sentinel,它们会每两秒一次,通过被监视的服务器的频道
    • __sentinel__:hello 频道发送消息,向其他sentinel宣告自己的存在
  • 多个sentinel 之间也会创建连接,用于传送命令
  • sentinel只会与主服务器和从服务器来创建命令连接和订阅连接
    • sentinel 与 sentinel 之间只创建命令连接
  • sentinel 默认每秒向实例(包括主库,从库,其他sentinel)发送ping 命令,
    • 根据实例对返回,判断实例是否在线
    • 当实例在指定时间内连续回复无效信息,则主库将判断为主观下线
  • 当sentinel 判断一个主库为主观下线,他会向其他sentinel 询问,看它们是否同意这个主库进入主观下线状态
  • 当sentinel收到足够多的主观下线投票之后,它会将主服务器判断为客观下线。
posted on 2017-08-02 11:09  Aiapple  阅读(309)  评论(0编辑  收藏  举报