zoukankan      html  css  js  c++  java
  • 第十六章 Sentinel

    由一个或多个Sentinel实例组成的Sentinel系统,监测任意多主从服务器,一旦某个主服务器下线并超过等待时间,会将其下的某个从服务器上升为主服务器,对其余从服务器发送复制命令,将它们归属到新的主服务器下的从服务器,并且会继续监视下线的服务器,等其重新上线后,将其设置为新主服务器下的从服务器。

    16.1 启动并初始化Sentinel

      当一个Sentinel启动时,它需要执行以下步骤:

    1. 初始化服务器
    2. 将普通的Redis服务器使用的代码替换成Sentinel专用代码
    3. 初始化Sentinel状态
    4. 根据给定的配置文件,初始化Sentinel的监视主服务器列表
    5. 创建连向主服务器的网络连接

      16.1.1 初始化服务器

      类似初始化一个普通的Redis服务器,但不需要还原数据库状态

      16.1.2 使用Sentinel专用代码

      将部分普通Redis服务器使用的代码替换成Sentinel专用代码。譬如设置指定端口,使用专有命令表,普通Redis服务器使用redifs.c/redisCommandTabel作为命令表,Sentinel使用sentinel.c/sentinelcmds作为服务器的命令表

      16.1.3 初始化Sentinel状态

      初始化一个sentinel.c/sentinelState结构,保存服务器中所有和Sentinel功能有关的状态,一般状态由redis.h/redisServer保存

    struct sentinelState{
        //当前纪元,用于实现故障转移
        uint64_t current_epoch;
        //保存了所有被这个sentinel监视的主服务器
        //字典的键是主服务器的名字
        //字典的值指向以一个sentinelRedisInstance结构的指针
        dict *masters;
    
        //是否进入了TILT模式
        int tilt;
    
        //目前正在执行的脚本的数量
        int running_scripts;
    
        //进入TILT模式的时间
        mstime_t tile_start_time;
    
        //最后一次执行时间处理器的时间
        mstime_t previous_time;
    
        //一个FIFO队列,包含了所有需要执行的用户脚本 
        list *scripts_queue;
    }sentinel;

      16.1.4 初始化Sentinel状态的master属性  

      每个sentinelRedisInstance结构代表一个被监视的Redis服务器实例,可以是主/从服务器,也可以是另一个Sentinel服务器

    typedef struct sentinelRedisInstance{
        //标识值,记录了实例的类型,以及该实例的当前状态。主服务器SRI_MASTER,从服务器SRI_SLAVE
        int flag;
        //实例的名字
        //主服务器的名字由用户配置
        //从服务器以及Sentinel的名字由Sentinel自动设置
        //格式为ip:port
        char *name;
        //从服务器,键为实例名,值为sentinelRedisInstance实例
        dict slaves; 
        //监听当前服务器的哨兵
        dict sentinels;
        
        //示例的运行ID
        char *runid;
    
        //配置纪元,用于实现故障转移
        unit64_t config_epoch;
        //实例的地址,保存着实例的IP地址和端口号
        sentinelAddr *addr;
    
        //实例无响应多少毫秒后被判定为主观下线
        mstime_t down_after_period;
        //判定这个实例为客观下线所需要的支持股票数量
        int quorum;
        //在执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量
        int parallel_syncs;
        //刷新故障迁移状态的最大时限
        mstime_t failover_timeout;
        //....
    
    }

       16.1.5 创建连向主服务器的网络连接

      向监视的主服务器发送连接请求(命令连接和订阅连接),成为主服务器的客户端,目的是可以向主服务器发送命令,从回复中获取相关信息。

    • 命令连接,用于向主服务器发送命令,并接收命令回复
    • 订阅连接,用于订阅主服务器的_sentinel_:hello频道,目的是发现监听目标服务器的其余Sentinel

    16.2 获取主服务器信息

      Sentinel每十秒一次向主服务器发送INFO命令,主服务器的回复中包含了自身信息和下属从服务器的信息,据此更新/新建对应的信息

      

    16.3 获取从服务器信息

      当Sentinel发现主服务器有新的从服务器出现时,会创建到从服务器的命令连接和订阅连接。创建命令连接后,每十秒一次向从服务器发送INFO命令,获得如下信息:

    • 从服务器运行ID run_id
    • 从服务器的角色role
    • 主服务器的IP地址master_host,以及主服务器的端口号master_port
    • 主从服务器的连接状态master_link_status
    • 从服务器的优先级slave_priority(用来挑选新主服务器)
    • 从服务器的复制偏移量slave_repl_offset(用来挑选新主服务器)

      据此对从服务器的实例进行更新

      

    16.4 向主服务器和从服务器发送信息

      默认,Sentinel每两秒一次通过命令连接向所有被监视的主服务器和从服务器的_sentinel_:hello频道发送信息

      

      其中"s_"开头代表Sentibel本身的信息,"m_"开头即目标服务器的信息

    16.5 接收来自主服务器和从服务器的频道信息

      每个Sentinel通过命令连接向_sentinel_:hello频道发送信息,又通过频道连接接收信息,多个Sentinel服务器监视同一个服务器,通过频道接收的信息会共享。

      当信息中记录的Sentinel信息和本身相同时,当前Sentinel会丢弃;当收到其余Sentinel发送的信息时,会更新自身存储的服务器信息

      

      16.5.1 更新sentinels字典

      每个Sentinel的服务器实例下有一个sentinels字典,保存了监听当前服务器的Sentinel信息。当收到其他Sentinel发送的信息,会根据其中的信息更新,对应服务器的信息以及更新/新建对应服务器下sentinels字典中的Sentinels信息。

      Sentinel通过接收频道信息获悉其余Sentinel的存在,并通过发送频道信息暴露自己。

      16.5.2 创建连向其他Sentinel的命令连接

      当发现新的Sentinel时,在16.5.1操作下,还会向新Sentinel建立命令连接,而新Sentinel也会跟当前Sentinel建立命令连接,以便后续相互发送命令,进行信息交换。

    16.6 检测主观下线状态

      默认,Sentinel每秒一次向所有创建了命令连接的服务器(主/从服务器及其他Sentinel)发送PING命令,以此判断对方是否在线。+PONG、-LOADING、-MASTERDOWN三种回复为有效回复,其余均为无效回复。

      Sentinel配置文件的down-after-milliseconds选项指定了判定为主观下线需要的时间。当一个服务器在判定时间内,均返回无效回复,则判定为主观下线,Sentinel会更新服务器实例的flags属性,打开SRI_DOWN标识。多个Sentinel的配置可能不同,导致同一服务器在不同Sentinel的主观下线状态不一致

      

    16.7 检查客观下线状态

      当Sentinel判定一个主服务器主观下线状态后,会向其余监听的Sentinel确定该主服务器的下线状态(包含主观下线和客观下线),当收集足够的下线判断后,会将主服务器追加判定为客观下线,并对主服务器执行故障转移操作

      16.7.1 发送SENTINEL is-master-down-by-addr命令

      Sentinel使用:

      SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>询问其他Sentinel是否同意主服务器下线

      16.7.2 接收SENTINEL is-master-down-by-addr命令

      其他Sentinel收到确认下线命令时,根据命令附带的参数,检查服务器是否下线,回复检查结果

      16.7.3 接收SENTINEL is-master-down-by-addr命令的回复

      回复包含了三个参数:

    1. down_state:检查结果,1代表已经下线、0代表未下线
    2. leader_runid:可以是*,否则是这个Sentinel选举的局部领头Sentinel的运行ID
    3. leader_epoch:配置纪元,一个计数器,代表当前选举的轮数,当leader_runid的值为*,则该值总为0

      根据其他Sentinel的返回,统计同意服务器的下线数量,当达到配置值时,更新服务器实例的flags属性,表示服务器已经进入客观下线的状态。如果下线的是主服务器,则继续进行故障转移操作

      

    16.8 选举领头Sentinel

      当主服务器下线时,监视的Sentinels会协商选举领头的Sentinel,由领头Sentinel对下线主服务器执行故障转移,以防并发。选举的规则和方法:

    • 所有在线的Sentinel都有资格
    • 每次进行领头选举后,不管成功与否,都会将每个参与选举的Sentinel的配置纪元的值自增一次
    • 在一个配置纪元中,所有Sentinel都有一次将某个Sentinel设置局部领头的机会,一次配置纪元中只能设置一次,做出选择后不能修改
    • 每个发现主服务器进入客观下线的Sentinel都会要求其他Sentinel将自己设置为局部领头Sentinel(通过在Sentinel is-master-down-by-addr中设置current_epoch和run_id)
    • 收到命令的Sentinel在回复中告诉请求方自己选举的Sentinel的run_id和选举轮数
    • 只要有一个Sentinel获取的票数大于总Sentinel的一半,则当选
    • 如果在规定时间内,没有结果,则在一段时间后,开启下一轮选举

    16.9 故障转移

      由领头Sentinel选出一个从服务器,将其转化成主服务器,并将其余从服务器改为复制新主服务器,当下线服务器上线时,将其设置为新主服务器的从服务器。

      16.9.1 选出新的主服务器

      将下线主服务器的所有从服务器保存到一个列表中,按照规则筛选:

    • 删除下线或断开状态的从服务器,保证剩余的服务器都在线
    • 删除最近5秒内没有回复领头Sentinel的INFO命令的从服务器,保证剩下的都能跟领头Sentinel正常通信
    • 删除与下线服务器断开连接太长的从服务器,保证剩下的服务器中保存的数据都是比较新的
    • 根据服务器的优先级对列表中剩余的服务器进行排序,选出优先级最大的服务器
    • 如果存在多个同最大优先级的服务器,按照从服务器的复制偏移量排序,选出其中复制偏移量最大的服务器
    • 如果存在多个同最大偏移量的服务器,按照从服务器的运行ID排序,选出其中最小的服务器

      向挑选中的服务器发送SLAVEOF no one命令,将其转换成主服务器

      16.9.2 修改从服务器的复制目标

      先剩余从服务器发送SLAVEOF命令,让它们转向复制新的主服务器

      16.9.3 将旧的主服务器变成从服务器

      当旧的主服务器重新上线,Sentinel会向它发送SLAVEOF命令

    人生就像蒲公英,看似自由,其实身不由己。
  • 相关阅读:
    Eclipse Notepad 插件
    Apache Subversion command line tools 命令行工具,可以用bat更新提交了
    兼容IE的Canvas
    CentOS访问Windows磁盘分区
    [ServiceStack.Text] .net序列化,反序列化组件(号称最快,支持 JSON,XML,JSV格式)
    使用 aspectjmavenplugin 编绎打包 使用aspectJ 的maven项目
    redis学习
    全面转向VS2005
    Orc vs Elf
    MSDN Library May 2006 Edition
  • 原文地址:https://www.cnblogs.com/walker993/p/14459910.html
Copyright © 2011-2022 走看看