【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; }
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30221425/viewspace-2676759/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MHA選擇主庫原始碼解析原始碼
- MySQL MHA原始碼解析MySql原始碼
- MHA原始碼分析原始碼
- 【MySQL】MHA原始碼之監控檢查(一)MySql原始碼
- MYSQL + MHA +keepalive + VIP安裝配置(二)--MHA的配置MySql
- MHA原始碼分析——環境部署原始碼
- Redis原始碼剖析之主從複製Redis原始碼
- 【MHA】mysql高可用之MHAMySql
- Mysql MHA部署-04MHA配置MySql
- mysql之MHAMySql
- MySQL MHA配置MySql
- MySQL MHA部署 Part 5 MHA部署指南MySql
- jQuery原始碼剖析 (二) - 選擇器jQuery原始碼
- 【Mysql】MHA的原理MySql
- MySQL MHA介紹MySql
- 【MySQL】MHA安裝MySql
- OkHttp 原始碼分析(二)—— 快取機制HTTP原始碼快取
- RecyclerView 原始碼分析(二) —— 快取機制View原始碼快取
- TMCache原始碼分析(二)---TMDiskCache磁碟快取原始碼快取
- Mysql MHA部署-03MHA軟體安裝MySql
- 深入koa原始碼(二):核心庫原理原始碼
- Mysql 5.7 MHA 高可用MySql
- MySQL MHA部署實戰MySql
- MySQL MHA高可用方案MySql
- mysql HA 方案(2):MHAMySql
- mysql HA 方案(3):MHAMySql
- mysql5.7MHA配置MySql
- MySQL MHA部署 Part 6 MHA故障轉移測試MySql
- lodash原始碼分析之快取方式的選擇原始碼快取
- MySQL MHA部署 Part 7 MHA手動切換測試MySql
- 【Mysql】MHA配置虛擬ipMySql
- 雲端計算學習路線原始碼框架筆記:Mysql原始碼二原始碼框架筆記MySql
- dataguard之主庫增加資料檔案--邏輯備庫相應的調整(二)
- mybatis原始碼學習:一級快取和二級快取分析MyBatis原始碼快取
- myBatis原始碼解析-二級快取的實現方式MyBatis原始碼快取
- Mysql MHA部署-05故障轉移MySql
- 基於 MHA 高可用的 MySQLMySql
- MySQL MHA詳細搭建過程MySql