高效能MySQL.讀書筆記(六)高可用性

笑天居士發表於2013-11-17

什麼是高可用性

每個應用對可用性的需求各不相同。在設定一個可用時間的目標之前,先問問自己,是不是確實需要達到這個目標。可用性每提高一點,所花費的成本都會遠超之前;可用性的效果和開銷的比例並不是線性的。需要保證多少可用時間,取決於能夠承擔多少成本。高可用性實際上是在當機造成的損失與降低當機時間所花費的成本之間取一個平衡。換句話說,如果需要花大量金錢去獲得更好的可用時間,但所帶來的收益卻很低,可能就不值得去做。總的來說,應用在超過一定的點以後追求更高的可用性是非常困難的,成本也會很高,因此我們建議設定一個更現實的目標並且避免過度設計。幸運的是,建立2個9或3個9的可用時間的目標可能並不困難,具體情況取決於應用。

有時人們將可用性定義成伺服器正在執行的時間段。我們認為可用性的定義還應該包括應用是否能以足夠好的效能處理請求。有許多方法可以讓一個伺服器保持執行,但服務並不是真正可用。對一個很大伺服器而言,重啟MySQL之後,可能需要幾個小時才能充分預熱以保證查詢請求的響應時間是可以接受的,即使伺服器只接收了正常流量的一小部分也是如此。

如果伺服器遭遇災難性故障,可能多少都會丟失一此資料,例如最近已經寫入二進位制日誌但尚未傳遞到備庫中的中繼日誌中的事務。你能夠容忍嗎?大多數應用能夠容忍;因為替代方案大多非常昂貴且複雜,或者有一些效能開銷。例如,可以使用同步複製,或是將二進位制日誌放到一個通過DRBD進行復制的裝置上,這樣就算伺服器完全失效也不用擔心丟失資料。(但整個資料中心也有可能會掉電。)

一個良好的應用架構通常可以降低可用性方面的需求,至少對部分系統而言是這樣的,良好的架構也更容易做到高可用。將應用中重要和不重要的部分進行分離可以節約不少工作量和金錢,因為對於一個更小的系統改進可用性會更容易。

 

如何實現高可用

提升平均失效時間(MTBF)

在分類整理當機事件並追查導致當機的根源時,我們發現,很多當機本來是有一些方法可以避免的。我們發現大部分當機事件都可以通過全面的常識性系統管理辦法來避免。

l      測試恢復工具和流程,包括從備份中恢復資料。

l      遵循最小許可權原則。

l      謹慎安排升級資料庫伺服器。

l      在升級前,使用諸如Percona Toolkit中的pt_uptrade之類的工具仔細檢查系統

l      除非能證明有效,否則禁用查詢快取。

l      避免使用複雜的特性,例如複製過濾和觸發器,除非確實需要。

l      定期檢查複製完整性。

l      歸檔並清理不需要的資料。

l      養成習慣,評估和管理系統的改變、狀態以及效能資訊。

降低平均恢復時間(MTTR)

可以通過減少恢復時間來獲得高可用性。事實上,一些人走得更遠,只專注於減少恢復時間的某個方面:通過在系統中建立冗餘來避免系統完全失效,並避免單點失效問題。

在降低恢復時間上進行投資是非常重要的,一個能提供冗餘和故障轉移能力的系統架構,則是降低恢復時間的關鍵環節。但實現高可用性不單單是一個技術問題,還有許多個人和組織的因素。組織和個人在避免當機和從當機事件中恢復的成熟度和能力層次各不相同。

團隊成員是最重要的高可用性資產,所以為恢復制定一個好的流程非常重要。擁有熟練技能、應變能力、訓練有素的員工,以及處理緊急事件的詳細文件和經過仔細測試的流程,對從當機中恢復有巨大的作用。但也不能完全依賴工具和系統,因為它們並不能理解實際情況的細微差別,有時候它們的行為在一般情況下是正確的,但在某些場景下去是個災難。

避免單點失效

找到並消除的可能失效的單點,並結合切換到備用元件的機制,這是一種通過減少恢復時間(MTTR)來改善可用性的方法。如果你夠聰明,有時候甚至能將實際的恢復時間降低至0,但總的來說這很困難。(即使一些非常引人注目的技術,例如昂貴的負載均衡器,在發現問題並進行反饋時也會導致一定的延遲。)

共享儲存或磁碟複製

共享儲存通常使用的是SAN。如果主伺服器掛了,備用伺服器可以掛載相同的檔案系統,執行需要的恢復操作,並在失效伺服器上的資料上啟動MySQL。這個過程會更快,因為備用伺服器已經啟動,MySQL隨時可以執行。當開始做故障轉移時,檢查檔案系統、恢復InnoDB以及預熱(Percona Server提供了一個新特性,能夠把buffer pool儲存下來並在重啟後還原,在使用共享儲存時能夠很好地工作。MySQL5.6也有相似的特性)是最有可能遇到延遲的地方,但檢測失效本身在許多設定中也會花費很長時間。

共享儲存可以避免除儲存外的其他任何元件失效所引起的資料丟失,併為非儲存元件建立冗餘提供可能。不過,共享儲存本身仍是可能失效的單點。如果MySQL崩潰等故障導致資料檔案損壞,可能會導致備用伺服器也無法恢復。

主動-主動訪問模式的共享儲存怎麼樣?

在一個SAN、NAS或者叢集檔案系統上以主動-主動模式執行多個例項怎麼樣?MySQL不能這麼做。因為MySQL並沒有被設計成和其他MySQL例項同步對資料的訪問,所以無法在同一份資料上開啟多個MySQL例項。

MySQL中最普遍使用的磁碟複製技術是DRBD,並結合Linux-HA專案中的工具使用。

由於在備用DRBD裝置上的寫入必須要在主裝置上的寫入完成之前,因此備用裝置的效能至少要和主裝置一樣,否則就會限制主裝置的寫入效能。帶電池寫快取的RAID控制器對DRBD而言幾乎是必需的,因為在沒有這樣的控制器時效能可能會很差。

DRBD和SAN很相似,DRBD是獲得一份複製的資料,而SAN則是使用同一份資料副本,所以DRBD沒有單點問題,但這兩種情況下,當啟動備用機器時,MySQL伺服器的快取都是空的。

DRBD有一些很好的特性和功能,但也有缺點:

l      DRBD故障轉移無法做到秒以內。它通常至少需要幾秒時間來將備用裝置提升成主裝置,這還不包括任何必須的檔案系統恢復和MySQL恢復。

l      它很昂貴,因為必須在主動-被動模式下執行。熱備伺服器的複製裝置因為處於被動模式,無法用於其他任務。連MySQL服務都是停用的。

l      對MyISAM表用處不大,因為MyISAM表崩潰後需要花費很長時間來檢查和修復。

l      DRBD無法代替備份。如果磁碟由於蓄意的破壞、誤操作、BUG或者其他硬體故障導致資料損壞,DRBD將無濟於事。此時複製的資料只是被損壞資料的完美副本。你需要使用備份(或MySQL延時複製)來避免這些問題。

l      對寫操作而言增加了負擔。網路往返開銷增加了寫入延遲。使用DRBD導致伺服器變慢最常見的原因是MySQL使用InnoDB並採取了完全持久化模式(innodb_flush_log_at_trx_commit=1),這會導致許多小的寫入和fsync()呼叫,通過DRBD同步時會非常慢。

 

MySQL同步複製

當使用同步複製時,主庫上的事務只有在至少一個備庫上提交後才能認為其執行完成。

MySQL本身並不支援同步提製(MySQL5.5只支援半同步複製。)

這裡可以在應用中加一個模擬方式,應用的業務在主庫上提交後,馬上連線到備庫,呼叫函式MASTER_POS_WAIT檢查備庫是否同主庫同步,但是這樣會極大增加主庫上業務提交返回的延遲。

基於複製的冗餘

複製管理器是使用標準MySQL複製來建立冗餘的工具。儘管可以通過複製來改善可用性,但也有一些“玻璃天花板”會阻止MySQL當前版本的非同步複製和半同步複製獲得和真正的同步複製相同的結果。複製無法保證實時的故障轉移和資料零丟失,也無法將所有節點等同對待。

複製管理器通常監控管理三件事:應用和MySQL間的通訊、MySQL伺服器的健康度,以及MySQL伺服器間的複製關係。它們即可以修改負載均衡的配置,也可以在必要的時候轉移虛擬IP地址以使應用連線到合適的伺服器上。大體上操作並不複雜:只需要確定寫入不會傳送到一個還沒有準備好提供寫服務的伺服器上,並保證當需要提升一臺備庫為主庫時記錄下正確的複製座標。

這聽起來在理論上是可行的,但實際經驗表明實際上並不總是能有效工作。事實上還很糟糕,有些時候最好有一些輕量級的工具集來幫助從覺的故障中恢復並以很低的開銷獲得較高的可用性。但很遺憾,到現在為止還沒有一個好的工具集可以可靠地完成這一點。

最好不要嘗試自己寫複製管理器。非同步元件有大量的故障形式,很多你從未親身經歷過,其中一些甚至無法理解,並且程式也無法適當處理,因此從這些非同步元件中得到正確的行為相當困難,並且可能遭遇資料丟失的危險。事實上,機器剛開始出現問題時,由一個經驗豐富的人來解決是很快的,但如果其他人做了一些錯誤的修復操作則可能導致問題更嚴重。

第一個複製管理器是MMM(http://mysql-mmm.org),但該工具集是否適用於生產環境部署的意見並不一致(儘管該工具的原作者也承認它並不可靠)。我們的許多客戶在自動故障轉移模式下使用該工具時確實遇到了許多嚴重的問題。它會導致健康的伺服器離線,也可能將寫入傳送到錯誤的地點,並將備庫移動到錯誤的座標。

另一個是比較新的工具是MHA工具集(http://code.google.com/p/mysql-master-ha/),MHA是很好的測試集,可以防止一些MMM遇到的問題,但是我們對該工具集還沒有更多的認識。

基於複製的冗餘最終來說好壞參半。只有在可用性的重要性遠比一致性或資料零丟失保證更重要時才推薦使用。例如,一些人並不會真正的從他們的網站功能中獲得,而是從它的可用性中賺錢。誰會在乎是否出現了故障導致一張照片丟失了幾條評論或其他什麼東西呢?只要廣告收益繼續滾滾而來,可能並不值得花更多成本去實現真正的高可用性。但是還是可以通過複製來建立“儘可能的”高可用性。,當遇到一些很難處理的嚴重當機時可能會有所幫助。這是一個大賭注,並且可能對大多數人而言太過於冒險,除非是那些老成的使用者。

問題是許多使用者不知道如何去證明自己有資格並評估複製“輪盤賭”是否適合他們。這有兩個方面的原因。第一,他們並沒有看到“玻璃天花板”,錯誤地認為一組虛擬IP地址、複製以及管理指令碼能夠實現真正的高可用性。第二,他們低估了技術的複雜度,因此也低估了嚴重故障發生後從中恢復的難度。一些人認為他們能夠使用基於複製的冗餘技術,但隨後他們可能會更希望選擇一個有更強保障的簡單系統。

請不要認為我們將這些技術說得無所不能而把MySQL自身的複製貶得一團糟,那不是我們的本意。你可以為DRBD寫出低質量的故障轉移指令碼,這很簡單,就像為MySQL複製編寫指令碼一樣。主要的區別是MySQL複製非常複雜,有很非常細小的差別,並且不會阻止你幹壞事。

 

故障轉移和故障恢復

提升備庫或切換角色

虛擬IP地址或IP接管

中介軟體解決方案

可以使用代理、埠轉發、網路地址轉換(NAT)或者硬體負載均衡來實現故障轉移和故障恢復。這些都是很好的解決方案,不像其它方法可能會引入一些不確定性(所有系統元件認同哪一個是主庫嗎?它能夠及時並原子地更改嗎?),它們是控制應用和伺服器間連線的中樞。但是,它們自身也引入了單點失效,需要準備冗餘來避免這個問題。

使用這樣的解決方案,你可以將一個遠端資料中心設定成看起來好像和應用在同一個網路裡。這樣就可以使用諸如浮動IP地址技術讓應用和一個完全不同的資料中心開始通訊。你可以配置每個資料中心的每臺應用伺服器,通過它自己的中介軟體連線,將流量路由到活躍資料中心的機器上。如果活躍資料中心的MySQL崩潰了,中介軟體可以路由流量到另外一個資料中心的伺服器池中,應用無須知道這個變化。

MySQL代理,我推薦國內淘寶的Cobar,文件齊全,挺好用的。

在應用中處理故障轉移

有時候讓應用來處理故障轉移會更簡單或者更加靈活。例如,如果應用遇到一個錯誤,這個錯誤外部觀察者正常情況下是無法察覺的,例如關於資料庫損壞的錯誤日誌資訊,那麼應用可以自己來處理故障轉移過程。

雖然把故障轉移處理過程整合到應用中看起來比較吸引人,但可能沒有想象中那麼有效。大多數應用有許多元件,例如cron任務、配置檔案,以及用不同語言編寫的指令碼。將故障轉移整合到應用中可能導致應用變得太過笨拙,尤其是當應用增大並變得更加複雜時。

但是將監控構建到應用中是一個好主意,當需要時,能夠立刻開始故障轉移過程。應用應該也能夠管理使用者體驗,例如提供降級功能,並顯示給使用者合適的資訊。

總結

增加執行時間,就要嘗試去防止故障發生。悲劇的是,在預防故障發生時,它仍然會覺得你做的不夠多,所以預防故障的努力經常會被忽視掉。

縮短恢復時間可能更復雜並且代價很高。從簡單和容易的方面來說,可以通過監控來更快地發現問題,並記錄大量的度量值以幫助診斷問題。

 

相關文章