注:这里面是由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失败。