知数堂第5期MySQL实战班学员,第10期MySQL优化班学员,现任职助教。

MHA在选择新的主库之前,会先把活着的slave分为几个数组,分别为latest(最靠前的slave数组),pref(优先被选择为master的数组),bad(不会被选择成为master的slave),slaves(所有活着的slave数组)。然后进行5次选择,从上面的这些组当中挑选出新的master。

选择latest数组

foreach (@slaves) {
my $a = $latest[0]{Master_Log_File};
my $b = $latest[0]{Read_Master_Log_Pos};
if (
!$find_oldest
&& (
( !$a && !defined($b) )
|| ( $_->{Master_Log_File} gt $latest[0]{Master_Log_File} )
|| ( ( $_->{Master_Log_File} ge $latest[0]{Master_Log_File} )
&& $_->{Read_Master_Log_Pos} > $latest[0]www.wanmeiyuele.cn{Read_Master_Log_Pos} )
)
)
{
@latest = ();
push( @latest, $_ );
}
elsif (
$find_oldest
&& (
( !$a && !defined($b) )
|| ( $_->{Master_Log_File} lt $latest[0]{Master_Log_File} )
|| ( ( $_->{Master_Log_File} le $latest[0]{Master_Log_File} )
&& $_->{Read_Master_Log_Pos} < $latest[0]{Read_Master_Log_Pos} )
)
)
{
@latest = ();
push( @latest, $_ );
}
elsif ( ( $_->{Master_Log_File} eq $latest[0]{Master_Log_File} )
&& ( $_->{Read_Master_Log_Pos} == $latest[0]{Read_Master_Log_Pos} ) )
{
push( @latest, $_ );
}
}

上面代码主要的结构就是一个foreach循环,一个if判断。foreach循环处理所有的活着的slave。if判断这里有三个判断条件,主要根据Master_Log_File和Read_Master_Log_Pos的大小来判断。第一个和第二个分别为了找出最靠前和最靠后的slave的。如果满足条件,那么就清空latest数组,把符合条件的放入latest数组里面。第三个条件用于找出和latest数组里面Master_Log_File和Read_Master_Log_Pos一样的slave,并放入latest数组。这样所有的 最靠前的就都放入latest数组里面了。

选择pref数组

foreach (@servers) {next if ( $_->{dead} eq '1' );if ( $_->{candidate_master} >= 1 ) {push( @ret_servers, $_ );}}

循环处理所有的配置server,已经死了的slave跳过,有参数candidate_master=1的slave放入pref数组,会被优先推举为新的master。

选择bad数组

 foreach (@servers) {if ($_->{no_master} >= 1|| $_->{log_bin}www.365soke.cn  eq '0'|| $_->{oldest_major_version} eq '0'|| ($latest_slave&& ( $check_replication_delay&& $self->check_slave_delay( $_, $latest_slave ) >= 1 ))){push( @ret_servers, $_ );}}

也是循环处理所有的配置的server,满足下面三个条件之一就会被选择放入bad数组,也就说这些slave不会被推选为新的master。

  1. 添加了参数no_master=1

  2. 没有开启binlog

  3. 如果延迟太大,如何才算是复制延迟太大呢?

 ( $latest->{Master_Log_File} gt $target->{Relay_Master_Log_File} )
|| ( $latest->{Read_Master_Log_Pos} >
$target->{Exec_Master_Log_Pos} + 100000000 )

这里的latest就是上面选择出来最靠前的第一个latest slave,不过所有的latest都是一样的,所以选择哪一个用于比较都是没关系的。要么latest的master_log_file > 对比者的Relay_Master_Log_File。或者是两者相同,但是latest的Read_Master_Log_Pos > 对比者的Exec_Master_Log_Pos+1亿。如果设置了参数check_repl_delay=0,那就不会会检查复制延迟。

选择slaves数组

只要是活着的slave都会被放进slaves数组当中。

这里需要说明的是,一个slave可以放进多个数组当中。不是一个slave只能存放到一个数组当中。

第一次选择:

return $latest[0] if ( $#pref <www.feihuanyule.com  0 && $#bad < 0 && $latest[0]->{latest_priority} );

如果pref和bad数组当中slave的个数为0,则选择latest数组当中的第一个slave为master。

第二次选择:

$log->info(
" Searching from candidate_master slaves which have received the latest relay log events.."
) if ( $#pref >= 0 );
foreach my $h (@latest) {
foreach my $p (@pref) {
if ( $h->{id} eq $p->{id} ) {
return $h
if ( !$self->get\_server\_from\_by\_id( \@bad, $p->{id} ) );
}
}
}
$log->info(" Not found.") if ( $#pref >= 0 );

循环对比latest数组和perf数组的slave,如果存在相同的slave,并且这个slave不在bad数组当中,该slave会被推选为新的master。

第三次选择:

foreach my $s (@slaves) {
foreach my $p (@pref)www.hbs90.cn/ {
if ( $s->{id} eq $p->{id} ) {
my $a = $self->get_server_from_by_id( \@bad, $p->{id} );
return $s unless ($a);
}
}
}

循环对比slaves数组pref数组当中的slave,如果有一个slave相同并且不在bad数组当中,该就会成为新的master。

第四次选择:

foreach my $h (@latest) {
my $a = $self->get_server_from_by_id( @bad, $h->{id} );
return $h unless ($a);
}

循环latest数组,如果有循环到的slave不在bad数组当中,这个slave就会成为master。也就是说就算添加了candidate_master=1,该slave也不一定会成为主库。

第五次选择:

foreach my $s (@slaves)www.yibaoyule1.com/ {
my $a = $self->get_server_from_by_id( @bad, $s->{id} );
return $s unless (www.huayi1.cn/ $a);
}

从活着的slave当中进行循环,如果循环到的slave不在bad数组当中,那么这个slave就会成为主库。 如果进行了5次选择都找不到主库,那么主库选择失败,failover失败。

转载于:https://www.cnblogs.com/qwangxiao/p/8836675.html

MHA选择主库源码解析相关推荐

  1. libev源码解析——定时器监视器和组织形式

    我们先看下定时器监视器的数据结构.(转载请指明出于breaksoftware的csdn博客) /* invoked after a specific time, repeatable (based o ...

  2. libev源码解析——定时器原理

    本文将回答<libev源码解析--I/O模型>中抛出的两个问题.(转载请指明出于breaksoftware的csdn博客) 对于问题1:为什么backend_poll函数需要指定超时?我们 ...

  3. libev源码解析——I/O模型

    在<libev源码解析--总览>一文中,我们介绍过,libev是一个基于事件的循环库.本文将介绍其和事件及循环之间的关系.(转载请指明出于breaksoftware的csdn博客) 目前i ...

  4. Redis源码解析——内存管理

    在<Redis源码解析--源码工程结构>一文中,我们介绍了Redis可能会根据环境或用户指定选择不同的内存管理库.在linux系统中,Redis默认使用jemalloc库.当然用户可以指定 ...

  5. Redis源码解析——前言

    今天开启Redis源码的阅读之旅.对于一些没有接触过开源代码分析的同学来说,可能这是一件很麻烦的事.但是我总觉得做一件事,不管有多大多难,我们首先要在战略上蔑视它,但是要在战术上重视它.除了一些高大上 ...

  6. python flask源码解析_用尽洪荒之力学习Flask源码

    [TOC] 一直想做源码阅读这件事,总感觉难度太高时间太少,可望不可见.最近正好时间充裕,决定试试做一下,并记录一下学习心得. 首先说明一下,本文研究的Flask版本是0.12. 首先做个小示例,在p ...

  7. Android之EasyPermissions源码解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 我们知道在Android中想要申请权限就需要在AndroidManifest ...

  8. Android之AsyncTask源码解析

    转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! ##前言 AsyncTask是一种轻量级的异步任务类,内部封装了Thread和Ha ...

  9. Go http源码解析(一)

    Go web之旅 此篇开始将开启Go web之旅,我将这趟旅途分为三个子旅程: 源码解析 框架解读 中间件使用 所以在这趟旅途中我们将领略源码之雄伟,框架之奇艳,中间件之灵秀.在接下来的时间里我会按照 ...

最新文章

  1. 【HDU 2814 扩展欧拉 a^b ≡ (a mod c)^b mod ϕ(c)+ϕ(c) modc,b=ϕ(c) 】
  2. mac下使用brew安装java等应用
  3. img之间出现缝隙的原因_神马情况?美缝剂施工出现脱胶是什么原因?
  4. .Net ViewState的实现(转载)
  5. How to use Emerge
  6. 解决Ubuntu16.04更新源时显示“暂时不能解析域名”问题
  7. sai教程初识SAI + 城堡绘画教程
  8. 我的求职之路——首战:毕马威(KPMG)笔试
  9. 上海二手房价数据分析
  10. logit回归怎么看显著性_[转载]spss logistic回归方程检验
  11. ASO优化之预算不够该如何做优化
  12. 中国数据中心最新规划图,中国数据中心建设情况
  13. jquery 实现的省市区级联,无ajax
  14. VS2015使用opencv
  15. css3渐变—渐变_玩渐变
  16. gensim corpora的简单使用
  17. Python技巧——解析式
  18. Hadoop HA (四) --------- YARN-HA 配置
  19. loss函数取对数的作用和意义
  20. 商店销售某一商品,商店每天公布统一的折扣(discount)。同时允许销售人员在销售时灵活掌握售价(price),

热门文章

  1. Django输入日期返回第几天time
  2. java面试题十七 switch使用范围
  3. java Socket(二)
  4. JavaScript实现单词首字母大写的方法集锦
  5. 《分布式系统》教学大纲
  6. Jupyter 绘图怎么显示中文
  7. geometry-api-java 学习笔记(二)点 Point
  8. kettle连接hadoophdfs图文详解
  9. 风控特:关系网络特征工程入门实践
  10. spark学习:ContextCleaner清理器