【Redis-6.0.8】哨兵源码解析下

1.sentinelHandleRedisInstance中哨兵的工作

参考上文中的2.4.2.1节,这一节给出来sentinelTimer中第二步sentinelHandleDictOfRedisInstances(sentinel.masters)-【对Sentinel监控的所有主节点进行递归式的执行周期性操作】的内容概要介绍.

1.1 sentinelReconnectInstance-重新建立连接

参考上文中的2.4.2.1.1节.

1.2 sentinelSendPeriodicCommands-发送监控命令

/* Send periodic PING, INFO, and PUBLISH to the Hello channel to
 * the specified master or slave instance. */
void sentinelSendPeriodicCommands(sentinelRedisInstance *ri) {
    mstime_t now = mstime();
    mstime_t info_period, ping_period;
    int retval;
 
    /* Return ASAP if we have already a PING or INFO already pending, or
     * in the case the instance is not properly connected. */
    /* 如果ri实例连接处于关闭状态,直接返回 */
    if (ri->link->disconnected) return;
 
    /* For INFO, PING, PUBLISH that are not critical commands to send we
     * also have a limit of SENTINEL_MAX_PENDING_COMMANDS. We don't
     * want to use a lot of memory just because a link is not working
     * properly (note that anyway there is a redundant protection about this,
     * that is, the link will be disconnected and reconnected if a long
     * timeout condition is detected. */
     
     /*
        对于不是发送如INFO,PING,PUBLISH等关键命令的请求,我们设置宏
        SENTINEL_MAX_PENDING_COMMANDS对最大请求数进行限制,我们不想连接
        对象在无法正常工作的情况下占用大量的内存(请注意,无论如何,我们
        还有一个冗余的保护措施,即如果检测到长时间的超时条件,连接将被断
        开连接并重新连接
        #define SENTINEL_MAX_PENDING_COMMANDS 100  
        内存保护策略
        如果待执行的命令大于100乘以连接的引用数,那么就返回 
     */
    if (ri->link->pending_commands >=
        SENTINEL_MAX_PENDING_COMMANDS * ri->link->refcount) return;
 
    /* If this is a slave of a master in O_DOWN condition we start sending
     * it INFO every second, instead of the usual SENTINEL_INFO_PERIOD
     * period. In this state we want to closely monitor slaves in case they
     * are turned into masters by another Sentinel, or by the sysadmin.
     *
     * Similarly we monitor the INFO output more often if the slave reports
     * to be disconnected from the master, so that we can have a fresh
     * disconnection time figure. */
     /*
       如果ri是从节点,且他的主节点处于故障状态的状态或者从节点和主节点断开复制了
    */
    if ((ri->flags & SRI_SLAVE) &&
        ((ri->master->flags & (SRI_O_DOWN|SRI_FAILOVER_IN_PROGRESS)) ||
         (ri->master_link_down_time != 0)))
    {
        /* 设置INFO命令的周期时间为1s */
        info_period = 1000;
    } else {
        /* 否则就是默认的10s 
           #define SENTINEL_INFO_PERIOD 10000
        */
        info_period = SENTINEL_INFO_PERIOD;
    }
 
    /* We ping instances every time the last received pong is older than
     * the configured 'down-after-milliseconds' time, but every second
     * anyway if 'down-after-milliseconds' is greater than 1 second. */
    /* 
       每次最后一次接收到的PONG的间隔时间比配置的 'down-after-milliseconds' 时间更长,
       但是如果 'down-after-milliseconds'大于1秒,则每秒钟进行一次ping
    */
    /* 获取down_after_period,过了down_after_period这段时间,就可以认为它下线了 */
    ping_period = ri->down_after_period;
    
    if (ping_period > SENTINEL_PING_PERIOD) ping_period = SENTINEL_PING_PERIOD;
 
    /* Send INFO to masters and slaves, not sentinels. */
    /*
      如果实例不是Sentinel节点且Sentinel节点从该数据节点(主节点或从节点)
      没有收到过INFO回复或者收到INFO回复超时,则发送INFO命令给主节点和从节点
   */
    if ((ri->flags & SRI_SENTINEL) == 0 &&
        (ri->info_refresh == 0 ||
        (now - ri->info_refresh) > info_period))
    {
        /* 发送INFO命令给主节点和从节点,具体见下文分析 */
        retval = redisAsyncCommand(ri->link->cc,
            sentinelInfoReplyCallback, ri, "%s",
            sentinelInstanceMapCommand(ri,"INFO"));
        /* 已发送未回复的命令个数加1 */
        if (retval == C_OK) ri->link->pending_commands++;
    }
 
    /* Send PING to all the three kinds of instances. */
    /* 如果发送和回复PING命令超时, 调用sentinelSendPing(ri),具体见下文分析 */
    if ((now - ri->link->last_pong_time) > ping_period &&
               (now - ri->link->last_ping_time) > ping_period/2) {
        sentinelSendPing(ri);
    }
 
    /* PUBLISH hello messages to all the three kinds of instances. */
    /* 如果发送频道的定时命令超时,调用sentinelSendHello,具体见下文分析 */
    if ((now - ri->last_pub_time) > SENTINEL_PUBLISH_PERIOD) {
        sentinelSendHello(ri);
    }
}



补充一些枚举值:
/* Note: times are in milliseconds. */
#define SENTINEL_INFO_PERIOD 10000
#define SENTINEL_PING_PERIOD 1000
#define SENTINEL_ASK_PERIOD 1000
#define SENTINEL_PUBLISH_PERIOD 2000
#define SENTINEL_DEFAULT_DOWN_AFTER 30000
#define SENTINEL_HELLO_CHANNEL "__sentinel__:hello"
#define SENTINEL_TILT_TRIGGER 2000
#define SENTINEL_TILT_PERIOD (SENTINEL_PING_PERIOD*30)
#define SENTINEL_DEFAULT_SLAVE_PRIORITY 100
#define SENTINEL_SLAVE_RECONF_TIMEOUT 10000
#define SENTINEL_DEFAULT_PARALLEL_SYNCS 1
#define SENTINEL_MIN_LINK_RECONNECT_PERIOD 15000
#define SENTINEL_DEFAULT_FAILOVER_TIMEOUT (60*3*1000)
#define SENTINEL_MAX_PENDING_COMMANDS 100
#define SENTINEL_ELECTION_TIMEOUT 10000
#define SENTINEL_MAX_DESYNC 1000
#define SENTINEL_DEFAULT_DENY_SCRIPTS_RECONFIG 1

1.2.1 INFO

1.上文中进行了如下调用:  
     {
       ...
       retval = redisAsyncCommand(ri->link->cc,
            sentinelInfoReplyCallback, ri, "%s",
            sentinelInstanceMapCommand(ri,"INFO"));
        if (retval == C_OK) ri->link->pending_commands++;
       ...
      }

2.看看redisAsyncCommand的实现
int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) {
    va_list ap;
    int status;
    va_start(ap,format);
    status = redisvAsyncCommand(ac,fn,privdata,format,ap);
    va_end(ap);
    return status;
}

3. sentinelInfoReplyCallback是处理INFO命令返回信息的回调函数,sentinelInfoReplyCallback
   很长,逻辑很多.

1.2.2 PING

1.2.3 PUBLISH

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值