导读
作者****:****魏新平
知数堂第5期MySQL实战班学员,第10期MySQL优化班学员,现任职助教。
MHA在选择新的主库之前,会先把活着的slave分为几个数组,分别为latest(最靠前的slave数组),pref(优先被选择为master的数组),bad(不会被选择成为master的slave),slaves(所有活着的slave数组)。然后进行5次选择,从上面的这些组当中挑选出新的master。
选择latest数组
1foreach (@slaves) { 2my $a = $latest[0]{Master_Log_File}; 3my $b = $latest[0]{Read_Master_Log_Pos}; 4if ( 5!$find_oldest 6&& ( 7( !$a && !defined($b) ) 8|| ( $_->{Master_Log_File} gt $latest[0]{Master_Log_File} ) 9|| ( ( $_->{Master_Log_File} ge $latest[0]{Master_Log_File} ) 10&& $_->{Read_Master_Log_Pos} > $latest[0]{Read_Master_Log_Pos} ) 11) 12) 13{ 14@latest = (); 15push( @latest, $_ ); 16} 17elsif ( 18$find_oldest 19&& ( 20( !$a && !defined($b) ) 21|| ( $_->{Master_Log_File} lt $latest[0]{Master_Log_File} ) 22|| ( ( $_->{Master_Log_File} le $latest[0]{Master_Log_File} ) 23&& $_->{Read_Master_Log_Pos} < $latest[0]{Read_Master_Log_Pos} ) 24) 25) 26{ 27@latest = (); 28push( @latest, $_ ); 29} 30elsif ( ( $_->{Master_Log_File} eq $latest[0]{Master_Log_File} ) 31&& ( $_->{Read_Master_Log_Pos} == $latest[0]{Read_Master_Log_Pos} ) ) 32{ 33push( @latest, $_ ); 34} 35}
上面代码主要的结构就是一个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数组
1foreach (@servers) { 2 next if ( $_->{dead} eq '1' ); 3 if ( $_->{candidate_master} >= 1 ) { 4 push( @ret_servers, $_ ); 5 } 6 }
循环处理所有的配置server,已经死了的slave跳过,有参数candidate_master=1的slave放入pref数组,会被优先推举为新的master。
选择bad数组
1 foreach (@servers) { 2 if ( 3 $_->{no_master} >= 1 4 || $_->{log_bin} eq '0' 5 || $_->{oldest_major_version} eq '0' 6 || ( 7 $latest_slave 8 && ( $check_replication_delay 9 && $self->check_slave_delay( $_, $latest_slave ) >= 1 ) 10 ) 11 ) 12 { 13 push( @ret_servers, $_ ); 14 } 15 }
也是循环处理所有的配置的server,满足下面三个条件之一就会被选择放入bad数组,也就说这些slave不会被推选为新的master。
-
添加了参数no_master=1
-
没有开启binlog
-
如果延迟太大,如何才算是复制延迟太大呢?
( $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 < 0 && $#bad < 0 && $latest[0]->{latest_priority} );
如果pref和bad数组当中slave的个数为0,则选择latest数组当中的第一个slave为master。
第二次选择:
1$log->info( 2" Searching from candidate_master slaves which have received the latest relay log events.." 3) if ( $#pref >= 0 ); 4foreach my $h (@latest) { 5foreach my $p (@pref) { 6if ( $h->{id} eq $p->{id} ) { 7return $h 8if ( !$self->get\_server\_from\_by\_id( \@bad, $p->{id} ) ); 9} 10} 11} 12$log->info(" Not found.") if ( $#pref >= 0 );
循环对比latest数组和perf数组的slave,如果存在相同的slave,并且这个slave不在bad数组当中,该slave会被推选为新的master。
第三次选择:
1foreach my $s (@slaves) { 2foreach my $p (@pref) { 3if ( $s->{id} eq $p->{id} ) { 4my $a = $self->get_server_from_by_id( \@bad, $p->{id} ); 5return $s unless ($a); 6} 7} 8}
循环对比slaves数组pref数组当中的slave,如果有一个slave相同并且不在bad数组当中,该就会成为新的master。
第四次选择:
1foreach my $h (@latest) { 2my $a = $self->get_server_from_by_id( @bad, $h->{id} ); 3return $h unless ($a); 4}
循环latest数组,如果有循环到的slave不在bad数组当中,这个slave就会成为master。也就是说就算添加了candidate_master=1,该slave也不一定会成为主库。
第五次选择:
1foreach my $s (@slaves) { 2my $a = $self->get_server_from_by_id( @bad, $s->{id} ); 3return $s unless ($a); 4}
从活着的slave当中进行循环,如果循环到的slave不在bad数组当中,那么这个slave就会成为主库。 如果进行了5次选择都找不到主库,那么主库选择失败,failover失败。
扫码加入知数堂技术交流QQ群
**(群号:**579036588)
群内可@各位助教了解更多课程信息





知数堂
叶金荣与吴炳锡联合打造
领跑IT精英培训
行业资深专家强强联合,倾心定制
MySQL实战/MySQL优化/大数据实战 / Python/ SQL优化
数门精品课程
紧随技术发展趋势,定期优化培训教案
融入大量生产案例,贴合企业一线需求
社群陪伴学习,一次报名,可学1年
DBA、开发工程师必修课
上千位学员已华丽转身,薪资翻番,职位提升
改变已悄然发生,你还在等什么?

扫码下载知数堂精品课程试听视频
或点击“阅读原文”直达下载地址
(MySQL 实战/优化、大数据实战、Python开发,及SQL优化等课程)
密码:hg3h



本文分享自微信公众号 - 老叶茶馆(iMySQL_WX)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。