您的位置:首页 > 数据库 > Redis

源码分析--redis的sentinel在master宕机时是如何选择新的master的

2021-03-05 21:15 1031 查看

redis通过sentinel, 在master宕机时,会迅速选择从库中的一个作为新的主库,然后其他的从库跟这个新主库重新建立主从关系。亲是否跟作者一样好奇--------假如一个redis主库有多个从库,最终会选择哪个从库作为新主库? 是否存在随机的情况? 您会给出什么样的答案。


上面图片的白色部分,是完整的主从切换日志。关于选择新主库,日志中只有如下所示的轻描淡写地一行。

“+selected-slave slave 197.3.XXX.44:6379  197.3.XXX.44  6379  @ mymaster 197.3.xxx.44 6381“ ,但是,选择新的主库,实际包含了非常多的细节。为了了解所有的细节,途径只有一个:从源码入手。

从从库中选择新主库的入口函数如下,sentinelFailoverSelectSlave:


光从函数名,我们就能知道其作用,分析一下上面的函数。

第一部分:sentinelRedisInstance *slave =sentinelSelectSlave(ri); 函数sentinelSelectSlave,这就真正执行从从库(slave)中选举新主库(master)的函数。 这个函数后面分析。

第二部分if (slave == NULL),也就是没有找到符合条件的从库,则日志中就会输出-failover-abort-no-good-slave 的信息,然后切换执行sentinelAbortFailover(ri);也就是切换中断。

第三部,也就是上面if条件的else部分,也就是找到新的主库,然后在日志文件中记录如上所述的日志“

+selected-slave slave 197.3.XXX.44:6379  197.3.XXX.44  6379  @ mymaster 197.3.xxx.44 6381” ,然后修改该新主库的标志,修改成 slave->flags |= SRI_PROMOTED; ,也就是即将提升为主库的状况promoted,同时修改正在切换的主库的一些信息,如现有的主库实例的promoted_slave属性上设置新主库实例的信息。(代码 ri->promoted_slave= slave;)


   如上面我们所述,选择新主库的真正功能函数是sentinelSelectSlave,咱们截取该函数中最核心的一段代码,如下图:


 我们来解析上面的代码:

 第一行(部分)   di =dictGetIterator(master->slaves); 该语句的作用就是取出包含master的所有slaves的列表,然后下面的代码就通过该列表,对每个slave 进行判断。 也就是下面的while循环。

 第二部分,将每个slave进入循环体进行判断,如果命中任何一个coutinue, 则该slave不合作为新主库的条件。猛然发现,作为新主库的条件还真不少。

1。 if(slave->flags & (SRI_S_DOWN|SRI_O_DOWN)) continue;

如果该slave的状态本身就是s-down或者o-down,就做了主库。

2. if(slave->link->disconnected) continue;

 如果该slave处于无法连接状态,pass.


3. if(mstime() - slave->link->last_avail_time >SENTINEL_PING_PERIOD*5) continue;

 如果slave_link_last_avail_time 是SENTINEL_PING_PERIOD*5 毫秒以前,SENTINEL_PING_PERIOD 的宏定义,值为1000, 也就是5秒以前。 而last_avail_time 的注释如下。

 mstime_t last_avail_time; /* Last time the instance replied to ping with

 a reply we consider valid. */


4. if (slave->slave_priority == 0) continue;

  如果该slave_priority 为0 , 是无法作为新主库的。


5. if (mstime() - slave->info_refresh > info_validity_time) continue;

 如果slave->info_refresh 也就是slave info的刷新时间在info_validity_time 毫秒之前,也是不能作为主库。


6.if(slave->master_link_down_time > max_master_down_time) continue;

   如果slave的master_link_down_time 大于max_master_down_time ,也是不能作为主库的。max_master_down_time 跟down_after_period有关,有下面的等式:

max_master_down_time += master->down_after_period * 10;


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: