温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

【MySQL】MHA源代码之主库选取(二)

发布时间:2020-08-08 21:08:04 来源:ITPUB博客 阅读:201 作者:风尘_NULL 栏目:MySQL数据库

MHA 选举主库所维护的数组

在讲MHA选择 master的代码中,我们必须把维护的四个数组的来龙去脉讲清楚

(1) Alive_slaves 数组 :

server不是 master,且从库正常, latest数组中的 server有足够的中继日志恢复这个落后的从库 (追上主库 ),则放入这个 Alive_slaves的数组中 (此段代码在 ServerManager.pminit_servers函数 )

    if ( $server->{dead} ) {       $self->add_dead_server($server);     }     elsif ( $server->{unmanaged} ) {       $self->add_unmanaged_slave($server);     }     #不是dead或者unmanaged就加入alive_server数组,如果show slave status 不是返回0E0,且这个server不是原来的主库,并且sql线程无误且可以用中继日志来恢复,就加入alive_slave数据,否则加入failed——slave数组     else {       $self->add_alive_server($server);       if ( $server->{not_slave} eq '0' && !$server->{orig_master} ) {         if ( !$server->is_sql_thread_error() && !$server->{lack_relay_log} ) {           $self->add_alive_slave($server);         }         else {           $self->add_failed_slave($server);         }       } }

(2)Latest 数组

alive_slaves数组中选取 relaylog最新的 server,这个数组如果有多个 server,serverRead_master_log_pos,master_log_file一定相等(此段代码在 ServerManager.pmidentify_latest_slaves函数)

 

 my @slaves = $self->get_alive_slaves();   my @latest = ();   foreach (@slaves) {     my $a = $latest[0]{Master_Log_File};     my $b = $latest[0]{Read_Master_Log_Pos};     if (       #find_oldest=0,即我们取的最全relaylog的slave,至于这里为什么是数组,是因为有最新的relaylog的不只有一个,可能有多个((即数组里边边的slave,具有一样的Read_Master_Log_     Pos位置))       !$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]{Read_Master_Log_Pos} )       )       )     {       @latest = ();       push( @latest, $_ ); }

(3)Perf 数组

这个无需多解释,就是MHA配置文件中配置了 candidate_master的值,这个可以大于 1

(4)Bad 数组: ( 代码见: ServerManager.pm:get_bad_candidate_masters)

1) 检测有故障的server

2) MHA 配置文件设置了 no_master server

3)log_bin 没有打开的server

4) 版本不兼容的server (高版本复制到低版本是没问题的,但是如果低版本的选为为主库,嘿嘿)

5) 复制落后太多的server

MHA 主库的选举

(1) 指定主库切换的,优先级最高(通常这是在手动切换)

(2) 如果server latest 数组中,且在 perf 数组中,则优先返回

(3) 如果server alive_servers 数组中,且在 perf 数组中,则优先返回

(4) 如果server lastest 中,则优先返回

(5) 如果server alive_servers 中,则返回

(6) 否则选举失败

这里优先级为1->6,具体实现在 (ServerManager.pm: select_new_master)

sub select_new_master {   my $self                    = shift;   my $prio_new_master_host    = shift;   my $prio_new_master_port    = shift;   my $check_replication_delay = shift;   $check_replication_delay = 1 if ( !defined($check_replication_delay) );     my $log    = $self->{logger};   my @latest = $self->get_latest_slaves();   my @slaves = $self->get_alive_slaves();     my @pref = $self->get_candidate_masters();   my @bad =     $self->get_bad_candidate_masters( $latest[0], $check_replication_delay );   #切换指定了master,即优先级最高的   if ( $prio_new_master_host && $prio_new_master_port ) {     my $new_master =       $self->get_alive_server_by_hostport( $prio_new_master_host,       $prio_new_master_port );     if ($new_master) {       my $a = $self->get_server_from_by_id( \@bad, $new_master->{id} );       unless ($a) {         $log->info("$prio_new_master_host can be new master.");         return $new_master;       }       else {         $log->error("$prio_new_master_host is bad as a new master!");         return;       }     }     else {       $log->error("$prio_new_master_host is not alive!");       return;     }   }     $log->info("Searching new master from slaves..");   $log->info(" Candidate masters from the configuration file:");   $self->print_servers( \@pref );   $log->info(" Non-candidate masters:");   $self->print_servers( \@bad );   #如果perf(candidate_master没设置)以及没有不符合(主从延迟,版本等)的slave,并且lastest[0]设置有优先级的话,就返回   return $latest[0]     if ( $#pref < 0 && $#bad < 0 && $latest[0]->{latest_priority} );   #如果设置了优先级,则从lastest数组中选择是canidate_master的,有就返回(隐含lastest[0]优先,如果lastest[0]同时是canidate_master,那肯定是优先返回的)   #latest_priority默认设置为1   if ( $latest[0]->{latest_priority} ) {     $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 );   }     #new master is not latest   #这里选择的是candidate_master,单不是latest数组中的master   $log->info(" Searching from all candidate_master slaves..")     if ( $#pref >= 0 );   foreach my $s (@slaves) {     foreach my $p (@pref) {       if ( $s->{id} eq $p->{id} ) {         my $a = $self->get_server_from_by_id( \@bad, $p->{id} );         return $s unless ($a);       }     }   }   $log->info("  Not found.") if ( $#pref >= 0 );   #其次是优先在lastest数组中,但不在candidate_master中的   if ( $latest[0]->{latest_priority} ) {     $log->info( " Searching from all slaves which have received the latest relay log events.."     );     foreach my $h (@latest) {       my $a = $self->get_server_from_by_id( \@bad, $h->{id} );       return $h unless ($a);     }     $log->info("  Not found.");   }     # none of latest servers can not be a master   $log->info(" Searching from all slaves..");   foreach my $s (@slaves) {     my $a = $self->get_server_from_by_id( \@bad, $s->{id} );     return $s unless ($a);   }   $log->info("  Not found.");     return; }


向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI