【MySQL】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数组,如果showslavestatus不是返回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)
subselect_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=1if(!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_hostcanbenewmaster.");return$new_master;}else{$log->error("$prio_new_master_hostisbadasanewmaster!");return;}}else{$log->error("$prio_new_master_hostisnotalive!");return;}}$log->info("Searchingnewmasterfromslaves..");$log->info("Candidatemastersfromtheconfigurationfile:");$self->print_servers(\@pref);$log->info("Non-candidatemasters:");$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默认设置为1if($latest[0]->{latest_priority}){$log->info("Searchingfromcandidate_masterslaveswhichhavereceivedthelatestrelaylogevents..")if($#pref>=0);foreachmy$h(@latest){foreachmy$p(@pref){if($h->{id}eq$p->{id}){return$hif(!$self->get_server_from_by_id(\@bad,$p->{id}));}}}$log->info("Notfound.")if($#pref>=0);}#newmasterisnotlatest#这里选择的是candidate_master,单不是latest数组中的master$log->info("Searchingfromallcandidate_masterslaves..")if($#pref>=0);foreachmy$s(@slaves){foreachmy$p(@pref){if($s->{id}eq$p->{id}){my$a=$self->get_server_from_by_id(\@bad,$p->{id});return$sunless($a);}}}$log->info("Notfound.")if($#pref>=0);#其次是优先在lastest数组中,但不在candidate_master中的if($latest[0]->{latest_priority}){$log->info("Searchingfromallslaveswhichhavereceivedthelatestrelaylogevents..");foreachmy$h(@latest){my$a=$self->get_server_from_by_id(\@bad,$h->{id});return$hunless($a);}$log->info("Notfound.");}#noneoflatestserverscannotbeamaster$log->info("Searchingfromallslaves..");foreachmy$s(@slaves){my$a=$self->get_server_from_by_id(\@bad,$s->{id});return$sunless($a);}$log->info("Notfound.");return;}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。