mysql主從同步(5)-同步延遲狀態考量(seconds_behind_master和pt-heartbea)

 

通常狀況下,咱們是經過"show slave status \G;"提供的Seconds_Behind_Master值來衡量mysql主從同步的延遲狀況。具體說明見:mysql主從同步(4)-Slave延遲狀態監控,這種方法在大多數狀況下確實是可行的。可是經驗告訴我,僅僅依靠Seconds_Behind_Master的值來監測主從同步數據是否延遲是絕對不可靠的!!!html

曾經遇到過的一個坑:
Mysql主從環境部署後,剛開始主從數據同步是沒問題的,也是經過監控Seconds_Behind_Master的值來判斷同步是否延遲。可是運行一段時間後,忽然有一天發現,主庫上寫入新數據後,從庫並無按時同步過來!!因而,馬上在從庫上執行"show slave status \G;"發現Seconds_Behind_Master爲0 ,而且Slave_IO_Running和Slave_SQL_Running線程狀態都是YES也就是說從庫到主庫的鏈接還在,沒有斷開!可是主庫上的變動數據就是長時間沒法同步到從庫上。若是沒有人爲干預,直到一個小時之後,從庫纔會自動從新鏈接主庫,進而才繼續同步主庫的變動
發生這種狀況時,經過通常的正常監控方式是不會發現從庫有數據延遲。因而可知,僅僅經過Seconds_Behind_Master=0來判斷同步是否延遲顯然是不夠滴.........mysql

發現這個問題之後,咱們人工干預的操做只是須要在從庫上執行下面兩步從新複製就能解決此問題:
mysql> stop slave;
mysql> start slave; sql

從新執行復制後,要儘快修改slave_net_timeout這個參數數據庫

之因此要等1小時才能從新同步,是由於slave_net_timeout這個參數默認的就是3600s,它是設置在多少秒沒收到主庫傳來的Binary Logs events以後,從庫認爲網絡超時,Slave IO線程會從新鏈接主庫。網絡

mysql> show variables like 'slave_net_timeout';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| slave_net_timeout | 3600  |
+-------------------+-------+
1 row in set (0.00 sec)

若是在部署mysql主從同步的時候,沒有在從庫這邊設置好slave_net_timeout這個參數,遇到上面的狀況,它就會按照默認的3600s(一小時)採起自動從新鏈接主庫,而後才能繼續同步主庫的變動。這個參數不能設置太大,太大會形成數據庫延遲或者主備庫直接的連接異常不能及時發現可是設置過小又會形成主庫沒有數據更新時頻繁重連。
至於slave_net_timeout這個參數究竟設置多少,要根據本身的mysql主庫數據更新的頻繁程度:主庫數據更新頻繁的,就將這個參數值設小點,更新不頻繁就設大點。
通常這個參數設置5s、10s、15s、20s、30s等等。運維

設置方法:
直接登錄從庫的mysql在線修改:工具

mysql> set global slave_net_timeout = 5;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> show variables like 'slave_net_timeout';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| slave_net_timeout | 5     |
+-------------------+-------+
1 row in set (0.01 sec)

或者在從庫的myc.nf裏添加:
[root@slave-server ~]# cat /usr/local/mysql/my.cnf
....
[mysqld]
.....
slave_net_timeout = 5
[root@slave-server ~]# /etc/init.d/mysql restartspa

所以,將這個參數設置恰當後,遇到上面問題的時候,從庫就會按照設定的時間去主動從新鏈接主庫同步數據,就不須要人工干預。線程

固然,上述場景是很是特殊的,通常出現的機率比較小,可是做爲運維人員,咱們很是有必要搞清楚該怎麼應對這種狀況。這就須要咱們要更加深刻的吃透MySQL replication重試機制。rest

接下來基於mysql主從複製原理來分析這一現象
MySQL的Replication是區別其餘數據庫很關鍵的地方,也是可擴展性和高可用的基礎。它自己已經很是智能化,只須要咱們調用Change Master指定Binlog 文件名和偏移位置就能夠搭建從主庫到備庫的複製關係。
MySQL複製線程會自動將目前複製位置記錄下來,在主備複製中斷的時候自動連上主庫,並從上次中斷的位置從新開始複製。這些操做都是全自動化的,不須要人爲的干預。這給了咱們運維人員帶來了不少便利,同時也隱藏了不少細節。要真正的理解前面問題的真相以及怎麼解決這個問題,咱們仍是須要真正的理解MySQL複製的原理。

1)Mysql主從複製的動做是「推」仍是「拉」
MySQL的複製是「推」的,而不是「拉」的。
「拉」是指MySQL的備庫不斷的循環詢問主庫是否有數據更新,這種方式資源消耗多,而且效率低。
「推」是指MySQL的主庫在本身有數據更新的時候推送這個變動給備庫,這種方式只有在數據有變動的時候纔會發生交互,資源消耗少。
顯而易見,「推」的方式更加符合程序運行的節能原則。

那麼MySQL具體是怎麼「推」的列呢?
實際上備庫在向主庫申請數據變動記錄的時候,須要指定從主庫Binlog的哪一個文件(MASTER_LOG_FILE)的具體多少個字節偏移位置(MASTER_LOG_POS)。對應的,主庫會啓動一個Binlog dump的線程,將變動的記錄從這個位置開始一條一條的發給備庫。備庫一直監聽主庫過來的變動,接收到一條,纔會在本地應用這個數據變動。

2)緣由解析
從上面的分析,咱們能夠大體猜到爲何 show slave status 顯示一切正常,可是實際上主庫的變動都沒法同步到備庫上來:
出現問題的時候,Binlog dump程序被kill掉了。而備庫做爲監聽的一方,它一直沒有收到任何變動,它會認爲主庫上長時間沒有任何變動,致使沒有變動數據推送過來。
備庫是沒法判斷主庫上對應的Binlog dump線程究竟是意外終止了,仍是長時間沒有任何數據變動的。因此,對這兩種狀況來講,備庫都顯示爲正常。

因此該問題的關鍵在於:
主庫Binlog dump線程kill的消息因爲網絡堵塞或者其餘緣由沒法發送到備庫,而備庫卻認爲主庫上的數據給有變動,由於雙方數據產生了差別。
而備庫只能在默認的3600s後主動地從新去鏈接主庫,屆時它纔會發現主庫的數據有變更了,纔會自動同步過來,這是須要等待很長時間。

3)問題避免
基於上面的分析,能夠知道MySQL在這種狀況下確實沒法避免,那麼有哪些辦法能夠避開:
   1--被動處理:修改延遲的監控方法,發現問題及時處理。
   2--主動預防:正確設置--master-retry-count ,--master-connect-retry ,--slave-net-timeout 複製重試參數。

   1--被動處理
   MySQL的延遲監控大部分直接採集show slave status中的Seconds_Behind_Master 。
   那麼像上面說的這種狀況下, Seconds_Behind_Master就沒法用來真實的衡量主備之間的複製延遲了。
   推薦使用Percona提供的監控方案(參考:mysql主從同步(3)-percona-toolkit工具(數據一致性監測、延遲監控)使用梳理

   2--主動預防
   除了手動在從庫上stop slave和start slave從新執行復制後,還須要指定三個參數,用於複製線程重連主庫,分別是
   master-retry-count:鏈接重試的次數。
   master-connect-retry:鏈接失敗後等待的秒數
   slave-net-timeout:上面已介紹
   其中 master-connect-retry 和 master-retry-count 須要在 Change Master 搭建主備複製時指定,而 slave-net-timeout 是一個全局變量,能夠在 MySQL 運行時在線設置。
   不過要注意的是:master-connect-retry和master-retry-count參數在Mysql5.6版本里就被去除了,因此Mysql5.6版本及更高版本就只設置slave-net-timeout參數即可。

  具體的重試策略爲:
  備庫過了slave-net-timeout秒尚未收到主庫來的數據,它就會開始第一次重試。而後每過 master-connect-retry 秒,備庫會再次嘗試重連主庫。直到重試了 master-retry-count 次,它纔會放棄重試。若是重   試的過程當中,連上了主庫,那麼它認爲當前主庫是好的,又會開始 slave-net-timeout 秒的等待。

  slave-net-timeout 的默認值是3600 秒, master-connect-retry默認爲60秒, master-retry-count默認爲86400次。  也就是說,若是主庫一個小時都沒有任何數據變動發送過來,備庫纔會嘗試重連主庫。  這就是爲何我遇到場景下,一個小時後,備庫纔會重連主庫,繼續同步數據變動的緣由。  這樣的話,若是你的主庫上變動比較頻繁,能夠考慮將slave-net-timeout設置的小一點,避免主庫 Binlog dump 線程 終止了,沒法將最新的更新推送過來。  固然 slave-net-timeout 設置的太小也有問題,這樣會致使若是主庫的變動確實比較少的時候,備庫頻繁的從新鏈接主庫,形成資源浪費。

相關文章
相關標籤/搜索