本篇文章給大家分享的是有關(guān)如何使用MySQL MHA源代碼進(jìn)行監(jiān)控檢查,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)技術(shù)團(tuán)隊(duì)10多年來致力于為客戶提供成都網(wǎng)站制作、網(wǎng)站建設(shè)、成都品牌網(wǎng)站建設(shè)、營(yíng)銷型網(wǎng)站、搜索引擎SEO優(yōu)化等服務(wù)。經(jīng)過多年發(fā)展,公司擁有經(jīng)驗(yàn)豐富的技術(shù)團(tuán)隊(duì),先后服務(wù)、推廣了上1000家網(wǎng)站,包括各類中小企業(yè)、企事單位、高校等機(jī)構(gòu)單位。
一、前言
在研究的同時(shí),把MHA的源代碼也翻閱了一遍,現(xiàn)在準(zhǔn)備把MHA一些重要內(nèi)容梳理一下,既然是高可用工具,那么健康檢測(cè)是一個(gè)基礎(chǔ)工作,只有正確檢測(cè)了數(shù)據(jù)庫的故障,才能進(jìn)行數(shù)據(jù)庫的切換;而MHA的布局亦如此:
二、MHA健康檢查核心調(diào)用函數(shù)鏈
注意我這里的函數(shù)調(diào)用鏈的規(guī)則是文件名|方法名,方法名中的或者表示的是,通過讀取配置文件,執(zhí)行其中的一個(gè)函數(shù)
MasterMonitor.pm|MHA::MasterMonitor::main()
->MasterMonitor.pm|MHA::MasterMonitor::wait_until_master_is_dead()
->MasterMonitor.pm|MHA::MasterMonitor::wait_until_master_is_unreachable()
->HealthCheck.pm|MHA::HealthCheck::wait_until_unreachable()
->HealthCheck.pm|MHA::HealthCheck::ping_select(或者)
->HealthCheck.pm|MHA::HealthCheck::ping_insert(或者)
->HealthCheck.pm|MHA::HealthCheck::ping_connect(或者)
三、代碼分析
我們主要看HealthCheck.pm|MHA::HealthCheck::wait_until_unreachable的實(shí)現(xiàn)
1) 該函數(shù)通過一個(gè)死循環(huán),檢測(cè)4次,每次sleep ping_interval秒(這個(gè)值在配置文件指定,參數(shù)是ping_interval),持續(xù)四次失敗,就認(rèn)為數(shù)據(jù)已經(jīng)宕機(jī)
2)如果有二路檢測(cè)腳本,需要二路檢測(cè)腳本檢測(cè)主庫宕機(jī),才是真正的宕機(jī),否則只是推出死循環(huán),結(jié)束檢測(cè),不切換
3)這里的GETLOCK(姑且說是分布式鎖)就是用來保護(hù)數(shù)據(jù)庫的訪問,防止腳本多次啟動(dòng)的
4)該函數(shù)調(diào)用了三種經(jīng)檢測(cè)方法,如下:
PING_TYPE_CONNECT(ping_select),PING_TYPE_INSERT(ping_insert),PING_TYPE_SELECT(ping select),但是哪種最好呢,我建議是PING_TYPE_CONNECT,實(shí)際上PING_TYPE_CONNECT調(diào)用了ping_select的方法,比PING_TYPE_CONNECT更具有可靠性
# main function # 返回1,表示數(shù)據(jù)庫有問題,但是不會(huì)切換;0表示數(shù)據(jù)庫有問題,會(huì)切換(這里同時(shí)還會(huì)返回ssh連接狀態(tài),方便確認(rèn)是網(wǎng)絡(luò)問題,還是數(shù)據(jù)庫問題) sub wait_until_unreachable($) { my $self = shift; my $log = $self->{logger}; my $ssh_reachable = 2; my $error_count = 0; my $master_is_down = 0; eval { while (1) { $self->{_tstart} = [gettimeofday]; if ( $self->{_need_reconnect} ) { #測(cè)試連接,連接正確返回0,否則返回1 ##這里有分布式GetLOCK,如果有別的會(huì)話,獲取了分布式鎖失敗,也算連接不成功 my ( $rc, $mysql_err ) = $self->connect( undef, undef, undef, undef, undef, $error_count ); if ($rc) { #排除權(quán)限錯(cuò)誤 if ($mysql_err) { if ( #在這里并不是不能訪問,可能只是權(quán)限錯(cuò)誤 grep ( $_ == $mysql_err, @MHA::ManagerConst::ALIVE_ERROR_CODES ) > 0 ) { $log->info( "Got MySQL error $mysql_err, but this is not a MySQL crash. Continue health check.." ); #sleep一段時(shí)間 $self->sleep_until(); #好吧,如果是權(quán)限錯(cuò)誤的話,就一直在這里循環(huán)了,那么檢測(cè)一致認(rèn)為mysql正常,打印權(quán)限日志就行 next; } } $error_count++; $log->warning("Connection failed $error_count time(s).."); #處理失敗,更新status_file為20:PING_FAILING $self->handle_failing(); #超過四次就跳出這個(gè)循環(huán)了 if ( $error_count >= 4 ) { #返回1表示ssh可以可以到達(dá),0表示ssh不能到達(dá) $ssh_reachable = $self->is_ssh_reachable(); #返回為1表示數(shù)據(jù)庫主庫已經(jīng)down,0則沒有down $master_is_down = 1 if ( $self->is_secondary_down() ); #退出循環(huán),last last if ($master_is_down); $error_count = 0; } $self->sleep_until(); next; } # connection ok $self->{_need_reconnect} = 0; $log->info( "Ping($self->{ping_type}) succeeded, waiting until MySQL doesn't respond.." ); } #釋放連接,如果只是類型為PING_TYPE_CONNECT $self->disconnect_if() if ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_CONNECT ); # Parent process forks one child process. The child process queries # from MySQL every <interval> seconds. The child process may hang on # executing queries. # DBD::mysql 4.022 or earlier does not have an option to set # read timeout, executing queries might take forever. To avoid this, # the parent process kills the child process if it won't exit within # <interval> seconds. my $child_exit_code; eval { if ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_CONNECT ) { $child_exit_code = $self->fork_exec( sub { $self->ping_connect() }, "MySQL Ping($self->{ping_type})" ); } elsif ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_SELECT ) { $child_exit_code = $self->fork_exec( sub { $self->ping_select() }, "MySQL Ping($self->{ping_type})" ); } elsif ( $self->{ping_type} eq $MHA::ManagerConst::PING_TYPE_INSERT ) { $child_exit_code = $self->fork_exec( sub { $self->ping_insert() }, "MySQL Ping($self->{ping_type})" ); } else { die "Not supported ping_type!\n"; } }; if ($@) { my $msg = "Unexpected error heppened when pinging! $@"; $log->error($msg); undef $@; $child_exit_code = 1; } if ( $child_exit_code == 0 ) { #ping ok #ping是成功的話,則更新狀態(tài),然后將$error_count=0(持續(xù)累積4次,那就是連接有問題) $self->update_status_ok(); if ( $error_count > 0 ) { $error_count = 0; } #handle_failing啟用了二路檢測(cè)以及ssh_check這時(shí)候沒結(jié)束需要kill掉 $self->kill_sec_check(); $self->kill_ssh_check(); } #存在其他分布式監(jiān)控 elsif ( $child_exit_code == 2 ) { $self->{_already_monitored} = 1; croak; } else { # failed on fork_exec $error_count++; $self->{_need_reconnect} = 1; $self->handle_failing(); } $self->sleep_until(); } $log->warning("Master is not reachable from health checker!"); }; if ($@) { my $msg = "Got error when monitoring master: $@"; $log->warning($msg); undef $@; return 2 if ( $self->{_already_monitored} ); return 1; } #$master_is_down=0,返回1 return 1 unless ($master_is_down); #0,$ssh_reachable返回1表示ssh可以可以到達(dá),0表示ssh不能到達(dá) return ( 0, $ssh_reachable ); } 1; 三種檢測(cè)機(jī)制函數(shù) #這個(gè)ping_connect正常返回0,錯(cuò)誤返回1或者2,1是連接存在問題,2是獲取鎖失敗 #改函數(shù)調(diào)用了ping_select sub ping_connect($) { my $self = shift; my $log = $self->{logger}; my $dbh; my $rc = 1; my $max_retries = 2; eval { my $ping_start = [gettimeofday]; #連接max_retries次,如果有錯(cuò)誤,則退出 while ( !$self->{dbh} && $max_retries-- ) { eval { $rc = $self->connect( 1, $self->{interval}, 0, 0, 1 ); }; if ( !$self->{dbh} && $@ ) { die $@ if ( !$max_retries ); } } #ping_select()正常返回為0,錯(cuò)誤返回為1 $rc = $self->ping_select(); # To hold advisory lock for some periods of time #獲取鎖可能需要一定時(shí)間,所以在釋放連接之前,需要等待一點(diǎn)時(shí)間 $self->sleep_until( $ping_start, $self->{interval} - 1.5 ); $self->disconnect_if(); }; if ($@) { my $msg = "Got error on MySQL connect ping: $@"; undef $@; $msg .= $DBI::err if ($DBI::err); $msg .= " ($DBI::errstr)" if ($DBI::errstr); $log->warning($msg) if ($log); $rc = 1; } return 2 if ( $self->{_already_monitored} ); return $rc; } #語句SELECT 1 As Value,正常返回0,錯(cuò)誤返回為1 sub ping_select($) { my $self = shift; my $log = $self->{logger}; my $dbh = $self->{dbh}; my ( $query, $sth, $href ); eval { $dbh->{RaiseError} = 1; $sth = $dbh->prepare("SELECT 1 As Value"); $sth->execute(); $href = $sth->fetchrow_hashref; if ( !defined($href) || !defined( $href->{Value} ) || $href->{Value} != 1 ) { die; } }; if ($@) { my $msg = "Got error on MySQL select ping: "; undef $@; $msg .= $DBI::err if ($DBI::err); $msg .= " ($DBI::errstr)" if ($DBI::errstr); $log->warning($msg) if ($log); return 1; } return 0; } #正常返回0,錯(cuò)誤返回1,有個(gè)疑問,這里見得數(shù)據(jù)庫表貌似沒有清理吧 sub ping_insert($) { my $self = shift; my $log = $self->{logger}; my $dbh = $self->{dbh}; my ( $query, $sth, $href ); eval { $dbh->{RaiseError} = 1; $dbh->do("CREATE DATABASE IF NOT EXISTS infra"); $dbh->do( "CREATE TABLE IF NOT EXISTS infra.chk_masterha (`key` tinyint NOT NULL primary key,`val` int(10) unsigned NOT NULL DEFAULT '0') engine=MyISAM" ); $dbh->do( "INSERT INTO infra.chk_masterha values (1,unix_timestamp()) ON DUPLICATE KEY UPDATE val=unix_timestamp()" ); }; if ($@) { my $msg = "Got error on MySQL insert ping: "; undef $@; $msg .= $DBI::err if ($DBI::err); $msg .= " ($DBI::errstr)" if ($DBI::errstr); $log->warning($msg) if ($log); return 1; } return 0; }
四、總結(jié)
1)數(shù)據(jù)庫MHA的健康檢查,最終調(diào)用的ping_select,ping_insert,ping_connect的一種,檢測(cè)的時(shí)間由ping_interval控制,其中ping_connect調(diào)用了ping_select
2)MHA最好配置二路檢測(cè),否則只是MHA主節(jié)點(diǎn)從自身ssh去檢測(cè)主庫是否正常,在MHA管理節(jié)點(diǎn)與主庫網(wǎng)絡(luò)存在問題的時(shí)候,有可能會(huì)發(fā)生誤切換
3)注意:這里只列出了核心函數(shù),其實(shí)在程序啟動(dòng)的時(shí)候,還有一些啟動(dòng)情況檢查,基本是主庫是否可連接,配置是否正確,從庫是否正常等等
以上就是如何使用MySQL MHA源代碼進(jìn)行監(jiān)控檢查,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
當(dāng)前文章:如何使用MySQLMHA源代碼進(jìn)行監(jiān)控檢查
分享地址:http://m.newbst.com/article48/gpjehp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、App開發(fā)、定制網(wǎng)站、做網(wǎng)站、域名注冊(cè)、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容