1.23 MySQL HA經驗談
Last updated
Last updated
之所以想寫這篇是因為有一次在跟某間公司的面試官聊天的時候, 對方問我說我所參與的某個專案的HA(High Availability)是怎麼做的, 但在回答的過程中我發現我並沒有好好的去了解這一段(因為有SE幫我們處理掉這段了, 我們只要專心寫邏輯就好), 想當然就是被reject了. 後來我就找我們的SE聊了一下這部分, 才知道了背後的來龍去脈. 儘管我們的做法其實也不是那麼的完美, 不過我想還是在此紀錄一下, 順便反省一下, 因為真的太混了.
在我參與到的這個專案中, 這個API module背後接的是MySQL, 而對於這套API/MySQL, 我們有兩處機房(以下簡稱colo)可以用來提供服務 --- 每個機房各放一組API module以及MySQL的master-slave集合, 並且使用MYSQL Replication機制來對當前colo的各台資料庫以及跨colo的資料庫進行資料同步並且達到HA的效果, 簡略的示意圖如下:
如圖所示,先看colo1的部分:
寫入的request流進系統, 經由VIP轉至colo1的web service. 再來, 對DB的寫入操作被導至colo1的MySQL1(Master), 我們有設定所有在Colo1的寫入動作都只會在這臺上進行. 若資料成功寫入MYSQL1, 會觸發以下三件事:
同步寫入資料至MySQL2 (Slave)
同步寫入資料至MySQL3 (Slave)
同步寫入資料至MySQL4 (這台是在另一個colo的master)
在上面的第3步, 又會觸發以下兩件事:
同步寫入資料至MySQL5 (Slave)
同步寫入資料至MySQL6 (Slave)
這其實是一種1對3的連鎖動作, 所謂的1對3是MySQL1對MySQL2/3/4 (圖中的橘線1/2/3), 而MySQL4又會更新MySQL5/6. 相對的, 若今天request是從colo2進來, 那麼就會變成MySQL4對MySQL5/6/1進行更新 (圖中的橘線1'/2'/3'), 然後再間接由MySQL1去更新MySQL2/3. 這樣子, 就可以確保在資料有正常寫入某一台master的情況下, 所有資料庫都有正確地被同步到.
再來看看異常的情況, 有時候我們可能會偵測到有Slow query的情況, 譬如SQL寫爛了, 導致查詢花太多時間甚至就timeout或是死在那裡之類的..., 這時候最差的情況下可能就是查不到資料導致程式出問題(timeout), 再來就要看怎麼調整SQL
另一種情況, 當寫入資料至MySQL1的時候,資料成功寫入master了,但這時MySQL1突然死了(據說有一次是機房人員踢到電源...), 導致後續對2/3/4的同步作業都無法進行了, 這時候就只能人工介入進行問題排除了. 除了物理上的除錯(把電源修好或是把server修好), 我們還可以手動trigger特定的batch job去繼續進行本來被中斷的同步作業. 當然這是在資料確實有寫入MySQL1並且在同步發生前, MySQL1掛掉的狀況。
最糟的就是這個了: 資料寫入MySQL1, 但還沒寫完MySQL1就死了, 這就真的是掉資料了, 儘管這時可以fail over到另一組機房繼續運作, 但剛才掉的那筆資料就是沒了. 這種情況必須視資料類型看是否能透過trigger某些job來解決(我們有些資料是會從別的DB複製一份到MySQL的, 有點類似快取/備份的概念).