欢迎光临
我们一直在努力

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


MHA
选举主库所维护的数组

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


(1)

Alive_slaves
数组
:

server不是
master,且从库正常,
latest数组中的
server有足够的中继日志恢复这个落后的从库
(追上主库
),则放入这个
Alive_slaves的数组中
(此段代码在
ServerManager.pm
init_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,
server
Read_master_log_pos,master_log_file一定相等(此段代码在
ServerManager.pm
identify_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;
}



赞(0)
【声明】:本博客不参与任何交易,也非中介,仅记录个人感兴趣的主机测评结果和优惠活动,内容均不作直接、间接、法定、约定的保证。访问本博客请务必遵守有关互联网的相关法律、规定与规则。一旦您访问本博客,即表示您已经知晓并接受了此声明通告。