天天看點

MySQL叢集節點當機,資料庫腦裂!如何排障?

作者介紹

王晶,中國移動dba,負責“移動雲”業務系統的資料庫內建架構設計、運維、優化等工作;擅長技術領域mysql,獲oracle頒發的“mysql dba”官方認證,熟悉mysql複制結構、mha、cluster等多種架構及運維優化。

發現故障的時間正值大年初二,在各種鋪天蓋地的拜年資訊和微信紅包之中,我發現了手機上的這條告警通知:

problem:disaster: galera cluster has node down。我生産環境的galera叢集有一個節點當機了。

可能有的人不太熟悉mysql galera叢集,下面先介紹一下出故障的叢集資訊。

pxc:  

我們生産上用的是percona的一個mysql分支版本,perconaxtradb cluster,簡稱pxc,這是一個可以實時同步的mysql叢集,基于廣播write set和事務驗證來實作多節點同時commit,沖突事務復原的功能。強資料一緻性保證。

galera replication原理總結:  

1. 事務在本地節點執行時采取樂觀政策,成功廣播到所有節點後再做沖突檢測;

2. 檢測出沖突時,本地事務優先被復原;

3. 每個節點獨立、異步執行隊列中的ws;

4. 事務t在a節點執行成功傳回用戶端後,其他節點保證t一定會被執行,是以有可能存在延遲,即虛拟同步。

galera複制的架構圖:  

MySQL叢集節點當機,資料庫腦裂!如何排障?

galera flow control:  

galera是同步複制(虛拟同步)方案,事務在本地節點(用戶端送出事務的節點)上送出成功時,其它節點保證執行該事務。在送出事務時,本地節點把事務複制到所有節點,之後各個節點獨立異步地進行certification test、事務插入待執行隊列、執行事務。然而,由于不同節點之間執行事務的速度不一樣,長時間運作後,慢節點的待執行隊列可能會越積越長,最終可能導緻事務丢失。

galera内部實作了flow control,作用就是協調各個節點,保證所有節點執行事務的速度大于隊列增長速度,進而避免丢失事務。

實作原理很簡單。整個galera cluster中,同時隻有一個節點可以廣播消息(資料),每個節點都會獲得廣播消息的機會(獲得機會後也可以不廣播),當慢節點的待執行隊列超過一定長度後,它會廣播一個fc_pause消息,是以節點收到消息後都會暫緩廣播消息,直到該慢節點的待執行隊列長度減小到一定長度後,galera cluster資料同步又開始恢複。

搞清楚上面的背景原理之後,繼續說明我的排障過程。

問題描述  

1月29日早10點08分接收到zabbix告警資訊,生産環境某子系統資料庫叢集節點1、2分别報活躍線程數超閥值,而且不斷升高。

從業務側嘗試通路了一下該子系統,發現系統頁面一直無法正常查詢資料及修改資料。登陸伺服器檢視cpu、io、記憶體情況均空閑。說明累計的活躍線程過高,已經影響到業務的正常通路了。

問題分析  

1、登陸zabbix告警節點1、2檢視資料庫show global status like ‘threads_running’情況發現threads_running線程不斷增高。

節點1:

| threads_running|  100     |

節點2:

| threads_running|  110     |

2、繼續檢視節點1、2資料庫的show processlist的情況,發現存在很多線程停在wsrep in pre-commit stage狀态(這意味着很多線程已經在節點發出commit,但将該sql發送到其他節點是處于獨立異步地進行certification test、事務插入待執行隊列的狀态)。這裡就明了為什麼會有活躍線程不斷增加了,原來是線程都停留在wsrep in pre-commit stage狀态。

3、進一步查找為什麼會有線程一直停留在wsrep in pre-commit stage狀态,show global status like ‘%wsrep%’,發現1、2節點接受隊列并無阻塞,也沒有發出流控。

但wsrep_evs_delayed報節點3的4567端口連接配接延遲。檢視節點1、2錯誤日志發現報“wsrep: (40a252ac, 'tcp://節點2:4567') reconnecting to 67f667d2 (tcp://節點3:4567), attempt 0”。檢視節點3的錯誤日志與wsrep_evs_delayed運作參數則報相反資訊,連接配接節點1和節點2的4567端口延遲。

這裡需要解釋一下4567端口的作用(wsrep_provider_options中的gmcast.listen_addr項:主要作用是叢集内監聽組員狀态,組員之間的通信(握手,鑒權,廣播,寫入集的複制)。

此時,問題原因已經明朗了,因為節點3與節點1、2的4567端口一直連接配接有延遲,是以在節點1、2執行的請求無法及時的複制給節點3執行,導緻節點1、2的活躍線程一直執行不完。

+------------------------------+-------------+

| variable_name                | value       |

| wsrep_local_recv_queue       | 0          |

| wsrep_local_recv_queue_avg   | 0.008711    |

| wsrep_flow_control_paused    | 0.000000    |

| wsrep_flow_control_sent      | 0          |

| wsrep_flow_control_recv      | 0          |

| wsrep_evs_delayed             | 節點3:4567 |

| variable_name                | value       |

| wsrep_local_recv_queue       | 0           |

| wsrep_local_recv_queue_avg   | 0.006193    |

| wsrep_flow_control_paused    | 0.000000    |

| wsrep_flow_control_sent      | 0           |

| wsrep_flow_control_recv      | 0          |

| wsrep_evs_delayed             |節點3:4567 |

4、因查詢資料庫狀态除wsrep_evs_delayed報連接配接延遲,其他并無異常現象,初步懷疑是網絡原因造成,排查網絡後,發現是因核心交換機與接入交換機之間的光子產品損壞導緻丢包,是以影響部分資料庫叢集之間的通信,才會出現以上問題。

在網絡修複期間,因資料庫叢集節點3延遲丢包嚴重,被資料庫叢集仲裁後踢出了叢集,剩餘的節點1和節點2在運作了大約半小時後也因延遲丢包嚴重,出現了腦裂現象。

這時緊急将資料庫叢集3個節點關閉,然後在每個節點執行mysqld_safe --wsrep-recover指令找出最新事務号節點作為主節點啟動,并在故障期間保持單節點運作。待網絡故障消除後,逐一啟動節點2、3,系統資料庫叢集恢複正常。

問題回顧  

1、 在pxc環境中,如果叢集各個節點的通信端口(4567)因為網絡的原因出現異常(因為叢集節點間通信采用的是同一網段,是以是共性的原因),應及時采取相應措施防止腦裂情況出現。例如上面故障中,因網絡原因導緻叢集節點數從3個變為2個,這時就應該及時地關閉剩餘2個節點中的一個節點,讓業務隻跑在單節點上,還能避免出現腦裂的情況。至少業務不會是以終斷。

否則剩餘的兩個節點很快也會被網絡丢包拖垮,會導緻整個叢集都停止服務,影響業務。當然在非多主的叢集中也可以通過設定“set global wsrep_provider_options=’pc.ignore_sb=true’;”來取消叢集判斷腦裂的情況(多主環境中不建議使用)。

2、可以将wsrep_evs_delayed作為一個監控項進行監控,并結合網絡監控進行适當的告警。

原文釋出時間為:2017-02-16

本文來自雲栖社群合作夥伴dbaplus