久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

如何使用MySQL MHA源代碼進(jìn)行監(jiān)控檢查

161次閱讀
沒有評論

共計(jì) 6880 個(gè)字符,預(yù)計(jì)需要花費(fèi) 18 分鐘才能閱讀完成。

本篇文章給大家分享的是有關(guān)如何使用 MySQL MHA 源代碼進(jìn)行監(jiān)控檢查,丸趣 TV 小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著丸趣 TV 小編一起來看看吧。

一、前言

在研究的同時(shí),把 MHA 的源代碼也翻閱了一遍,現(xiàn)在準(zhǔn)備把 MHA 一些重要內(nèi)容梳理一下,既然是高可用工具,那么健康檢測是一個(gè)基礎(chǔ)工作,只有正確檢測了數(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),檢測 4 次,每次 sleep ping_interval 秒 (這個(gè)值在配置文件指定, 參數(shù)是 ping_interval), 持續(xù)四次失敗,就認(rèn)為數(shù)據(jù)已經(jīng)宕機(jī)

 2) 如果有二路檢測腳本,需要二路檢測腳本檢測主庫宕機(jī),才是真正的宕機(jī),否則只是推出死循環(huán),結(jié)束檢測,不切換

 3) 這里的 GETLOCK(姑且說是分布式鎖) 就是用來保護(hù)數(shù)據(jù)庫的訪問,防止腳本多次啟動的

 4) 該函數(shù)調(diào)用了三種經(jīng)檢測方法,如下:

 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ù)庫有問題,但是不會切換;0 表示數(shù)據(jù)庫有問題,會切換(這里同時(shí)還會返回 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} ) {
 # 測試連接,連接正確返回 0,否則返回 1
 ## 這里有分布式 GetLOCK,如果有別的會話,獲取了分布式鎖失敗,也算連接不成功
 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)了,那么檢測一致認(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 啟用了二路檢測以及 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 );
三種檢測機(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 的一種,檢測的時(shí)間由 ping_interval 控制,其中 ping_connect 調(diào)用了 ping_select

 2)MHA 最好配置二路檢測,否則只是 MHA 主節(jié)點(diǎn)從自身 ssh 去檢測主庫是否正常,在 MHA 管理節(jié)點(diǎn)與主庫網(wǎng)絡(luò)存在問題的時(shí)候,有可能會發(fā)生誤切換

 3) 注意:這里只列出了核心函數(shù),其實(shí)在程序啟動的時(shí)候,還有一些啟動情況檢查,基本是主庫是否可連接,配置是否正確,從庫是否正常等等

以上就是如何使用 MySQL MHA 源代碼進(jìn)行監(jiān)控檢查,丸趣 TV 小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注丸趣 TV 行業(yè)資訊頻道。

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-07-28發(fā)表,共計(jì)6880字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 大英县| 江陵县| 胶南市| 昔阳县| 莱州市| 旌德县| 鹤峰县| 黑河市| 和硕县| 尖扎县| 溧水县| 青河县| 浪卡子县| 吴旗县| 九寨沟县| 友谊县| 丹阳市| 靖州| 廉江市| 英德市| 潮安县| 新宾| 佛冈县| 古田县| 五原县| 黔江区| 邵武市| 阳原县| 华安县| 夹江县| 平遥县| 合山市| 本溪市| 大埔区| 新竹县| 同江市| 阿拉尔市| 马尔康县| 德钦县| 昌江| 增城市|