MHA选择主库源码解析
知數堂第5期MySQL實戰班學員,第10期MySQL優化班學員,現任職助教。
MHA在選擇新的主庫之前,會先把活著的slave分為幾個數組,分別為latest(最靠前的slave數組),pref(優先被選擇為master的數組),bad(不會被選擇成為master的slave),slaves(所有活著的slave數組)。然后進行5次選擇,從上面的這些組當中挑選出新的master。
選擇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]www.wanmeiyuele.cn{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, $_ ); } }上面代碼主要的結構就是一個foreach循環,一個if判斷。foreach循環處理所有的活著的slave。if判斷這里有三個判斷條件,主要根據Master_Log_File和Read_Master_Log_Pos的大小來判斷。第一個和第二個分別為了找出最靠前和最靠后的slave的。如果滿足條件,那么就清空latest數組,把符合條件的放入latest數組里面。第三個條件用于找出和latest數組里面Master_Log_File和Read_Master_Log_Pos一樣的slave,并放入latest數組。這樣所有的 最靠前的就都放入latest數組里面了。
選擇pref數組
foreach (@servers) {next if ( $_->{dead} eq '1' );if ( $_->{candidate_master} >= 1 ) {push( @ret_servers, $_ );}}循環處理所有的配置server,已經死了的slave跳過,有參數candidate_master=1的slave放入pref數組,會被優先推舉為新的master。
選擇bad數組
foreach (@servers) {if ($_->{no_master} >= 1|| $_->{log_bin}www.365soke.cn? 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。
添加了參數no_master=1
沒有開啟binlog
如果延遲太大,如何才算是復制延遲太大呢?
這里的latest就是上面選擇出來最靠前的第一個latest slave,不過所有的latest都是一樣的,所以選擇哪一個用于比較都是沒關系的。要么latest的master_log_file > 對比者的Relay_Master_Log_File。或者是兩者相同,但是latest的Read_Master_Log_Pos > 對比者的Exec_Master_Log_Pos+1億。如果設置了參數check_repl_delay=0,那就不會會檢查復制延遲。
選擇slaves數組
只要是活著的slave都會被放進slaves數組當中。
這里需要說明的是,一個slave可以放進多個數組當中。不是一個slave只能存放到一個數組當中。
第一次選擇:
return $latest[0] if ( $#pref <www.feihuanyule.com 0 && $#bad < 0 && $latest[0]->{latest_priority} );如果pref和bad數組當中slave的個數為0,則選擇latest數組當中的第一個slave為master。
第二次選擇:
$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。
第三次選擇:
foreach my $s (@slaves) { foreach my $p (@pref)www.hbs90.cn/ { 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。
第四次選擇:
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也不一定會成為主庫。
第五次選擇:
foreach my $s (@slaves)www.yibaoyule1.com/ { my $a = $self->get_server_from_by_id( @bad, $s->{id} ); return $s unless (www.huayi1.cn/?$a); }從活著的slave當中進行循環,如果循環到的slave不在bad數組當中,那么這個slave就會成為主庫。 如果進行了5次選擇都找不到主庫,那么主庫選擇失敗,failover失敗。
轉載于:https://www.cnblogs.com/qwangxiao/p/8836675.html
總結
以上是生活随笔為你收集整理的MHA选择主库源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js 手机端触发事事件、javascri
- 下一篇: Hive学习之路 (十六)Hive分析窗