注:这里面是由perl语言编写面视时候少有人会问到,仅供参考了解
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]{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, $_ );
}
}
pref数组 candidate_master
foreach (@servers) {
? ? next if ( $_->{dead} eq '1' );
? ? if ( $_->{candidate_master} >= 1 ) {
? ? ? push( @ret_servers, $_ );
? ? }
? }
bad 数组
foreach (@servers) {
? ? if (
? ? ? ? $_->{no_master} >= 1
? ? ? || $_->{log_bin} 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 )
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 );
? 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 );
? return $latest[0]
? ? if ( $#pref < 0 && $#bad < 0 && $latest[0]->{latest_priority} );
? 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
? $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 );
? 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;
}
第一次选择:
return $latest[0] if ( $#pref < 0 && $#bad < 0 && $latest[0]->{latest_priority} );
如果pref和bad数组当中slave的个数为0,则选择latest数组当中的第一个slave为master。
只有lastest ,没有 pref 没有 bad? , 选择最接近主库日志的slave
第二次选择:
$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。
1. lastest? db02? >? db03? db02=db03
2. pref? ? db03
3. db03? ? 不在 bad中
第三次选择:
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);
}
}
}
循环对比slaves数组pref数组当中的slave,如果有一个slave相同并且不在bad数组当中,该就会成为新的master。
slaves数组: 活着的? db02? ,db03
pref? ? ? : 备选的? db03
第四次选择:
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也不一定会成为主库。
pref 和bad 同时满足的节点??赡懿槐谎≡裎轮?。
第五次选择:
foreach my $s (@slaves) {
my $a = $self->get_server_from_by_id( @bad, $s->{id} );
return $s unless ($a);
}
从活着的slave当中进行循环,如果循环到的slave不在bad数组当中,那么这个slave就会成为主库。 如果进行了5次选择都找不到主库,那么主库选择失败,failover失败。