MySQL的高可用性
本章將講述提到的復(fù)制、可擴展性以及髙可用性三個主題中的第三個。歸根結(jié)底,高可用性實際上意味著“更少的宕機時間”。然而糟糕的是,高可用性經(jīng)常和其他相關(guān)的概念混淆,例如冗余、保障數(shù)據(jù)不丟失,以及負(fù)載均衡。我們希望另外的兩章已經(jīng)很清楚地理解高可用性做了足夠的鋪墊。跟其他兩章一樣,這一章也不僅僅是關(guān)注高可用性的內(nèi)容,一些相關(guān)的話題也會綜合闡述。
1.什么是高可用性
髙可用性實際上有點像神秘的野獸。它通常以百分比表示,這本身也是一種暗示:髙可用性不是絕對的,只有相對更髙的可用性。100%的可用性是不可能達(dá)到的。可用性的“9”規(guī)則是表示可用性目標(biāo)最普遍的方法。你可能也知道,“5個9”表示99.999%的正常可用時間。換句話說,每年只允許5分鐘的宕機時間。對于大多數(shù)應(yīng)用這已經(jīng)是令人驚嘆的數(shù)字,盡管還有一些人試圖獲得更多的“9”。
每個應(yīng)用對可用性的需求各不相同。在設(shè)定一個可用時間的目標(biāo)之前,先問問自己,是不是確實需要達(dá)到這個目標(biāo)。可用性每提高一點,所花費的成本都會遠(yuǎn)超之前;可用性的效果和開銷的比例并不是線性的。需要保證多少可用時間,取決于能夠承擔(dān)多少成本。高可用性實際上是在宕機造成的損失與降低宕機時間所花費的成本之間取一個平衡。換句話說,如果需要花大量金錢去獲得更好的可用時間,但所帶來的收益卻很低,可能就不值得去做。總的來說,應(yīng)用在超過一定的點以后追求更高的可用性是非常困難的,成本也會很高,因此我們建議設(shè)定一個更現(xiàn)實的目標(biāo)并且避免過度設(shè)計。幸運的是,建立2個9或3個9的可用時間的目標(biāo)可能并不困難,具體情況取決于應(yīng)用。
有時候人們將可用性定義成服務(wù)正在運行的時間段。我們認(rèn)為可用性的定義還應(yīng)該包括應(yīng)用是否能以足夠好的性能處理請求。有許多方法可以讓一個服務(wù)器保持運行,但服務(wù)并不是真正可用。對一個很大的服務(wù)器而言,重啟MySQL之后,可能需要幾個小時才能充分預(yù)熱以保證査詢請求的響應(yīng)時間是可以接受的,即使服務(wù)器只接收了正常流量的一小部分也是如此。
另一個需要考慮的問題是,即使應(yīng)用并沒有停止服務(wù),但是否可能丟失了數(shù)據(jù)。如果服務(wù)器遭遇災(zāi)難性故障,可能多少都會丟失一些數(shù)據(jù),例如最近已經(jīng)寫入(最新丟失的)二進(jìn)制日志但尚未傳遞到備庫的中繼日志中的事務(wù)。你能夠容忍嗎?大多數(shù)應(yīng)用能夠容忍;因為替代方案大多非常昂貴且復(fù)雜,或者有一些性能開銷。例如,可以使用同步復(fù)制,或是將二進(jìn)制日志放到一個通過DRBD進(jìn)行復(fù)制的設(shè)備上,這樣就算服務(wù)器完全失效也不用擔(dān)心丟失數(shù)據(jù)。(但是整個數(shù)據(jù)中心也有可能會掉電。)
一個良好的應(yīng)用架構(gòu)通常可以降低可用性方面的需求,至少對部分系統(tǒng)而言是這樣的,良好的架構(gòu)也更容易做到高可用。將應(yīng)用中重要和不重要的部分進(jìn)行分離可以節(jié)約不少工作量和金錢,因為對于一個更小的系統(tǒng)改進(jìn)可用性會更容易。可以通過計算“風(fēng)險敞口(riskexposure)”,將失效概率與失效代價相乘來確認(rèn)高優(yōu)先級的風(fēng)險。畫一個簡單的風(fēng)險計算表,以概率、代價和風(fēng)險敞口作為列,這樣很容易找到需要優(yōu)先處理的項目。
在<MySQL的可擴展性>通過討論如何避免導(dǎo)致糟糕的可擴展性的原因,來推出如何獲得更好的可擴展性。這里也會使用相似的方法來討論可用性,因為相信,理解可用性最好的方法就是研究它的反面——宕機時間。接下來的小節(jié)會討論為什么會出現(xiàn)宕機。
2.導(dǎo)致宕機的原因
我們經(jīng)常聽到導(dǎo)致數(shù)據(jù)庫宕機最主要的原因是編寫的SQL査詢性能很差,真的是這樣嗎?2009年我們決定分析我們客戶的數(shù)據(jù)庫所遇到的問題,以找出那些真正引起宕機的問題,以及如何避免這些問題。結(jié)果證實了一些我們已有的猜想,但也否定了一些(錯誤的)認(rèn)識,我們從中學(xué)到了很多。
我們首先對宕機事件按表現(xiàn)方式而非導(dǎo)致的原因進(jìn)行分類。一般來說,“運行環(huán)境”是排名第一的宕機類別,大約35%的事件屬于這一類。運行環(huán)境可以看作是支持?jǐn)?shù)據(jù)庫服務(wù)器運行的系統(tǒng)和資源集合,包括操作系統(tǒng)、硬盤以及網(wǎng)絡(luò)等。性能問題緊隨其后,也是約占35% ;然后是復(fù)制,占20%;最后剩下的10%包含各種類型的數(shù)據(jù)丟失或損壞,以及其他問題。
我們對事件按類型進(jìn)行分類后,確定了導(dǎo)致這些事件的原因。以下是一些需要注意的地方:
在運行環(huán)境的問題中,最普遍的問題是磁盤空間耗盡。
在性能問題中,最普遍的宕機原因確實是運行很糟糕的SQL,但也不一定都是這個原因,比如也有很多問題是由于服務(wù)器Bug或錯誤的行為導(dǎo)致的。
糟糕的Schema和索引設(shè)計是第二大影響性能的問題。
復(fù)制問題通常由于主備數(shù)據(jù)不一致導(dǎo)致。
數(shù)據(jù)丟失問題通常由于DROPTABLE的誤操作導(dǎo)致,并總是伴隨著缺少可用備份的問題。
復(fù)制雖然常被人們用來改善可用時間,但卻也可能導(dǎo)致宕機。這主要是由于不正確的使用導(dǎo)致的,即便如此,它也闡明了一個普遍的情況:許多高可用性策略可能會產(chǎn)生反作用,我們會在后面討論這個話題。
現(xiàn)在我們已經(jīng)知道了主要宕機類別,以及有什么需要注意,下面我們將專門介紹如何獲得高可用性。
3.如何實現(xiàn)高可用性
可以通過同時進(jìn)行以下兩步來獲得高可用性。首先,可以嘗試避免導(dǎo)致宕機的原因來減少宕機時間。許多問題其實很容易避免,例如通過適當(dāng)?shù)呐渲谩⒈O(jiān)控,以及規(guī)范或安全保障措施來避免人為錯誤。第二,盡量保證在發(fā)生宕機時能夠快速恢復(fù)。最常見的策略是在系統(tǒng)中制造冗余,并且具備故障轉(zhuǎn)移能力。這兩個維度的髙可用性可以通過兩個相關(guān)的度量來確定:平均失效時間(MTBF)和平均恢復(fù)時間(MTTR)。一些組織會非常仔細(xì)地追蹤這些度量值。
第二步——通過冗余快速恢復(fù)——很不幸,這里是最應(yīng)該注意的地方,但預(yù)防措施的投資回報率會很髙。接下來我們來探討一些預(yù)防措施。
3.1 提升平均失效時間(MTBF)
其實只要盡職盡責(zé)地做好一些應(yīng)做的事情,就可以避免很多宕機。在分類整理宕機事件并追查導(dǎo)致宕機的根源時,我們還發(fā)現(xiàn),很多宕機本來是有一些方法可以避免的。我們發(fā)現(xiàn)大部分宕機事件都可以通過全面的常識性系統(tǒng)管理辦法來避免。以下是從我們的白皮書中摘錄的指導(dǎo)性建議,在白皮書中有我們詳細(xì)的分析結(jié)果。
測試恢復(fù)工具和流程,包括從備份中恢復(fù)數(shù)據(jù)。
遵從最小權(quán)限原則。
保持系統(tǒng)干凈、整潔。
使用好的命名和組織約定來避免產(chǎn)生混亂,例如服務(wù)器是用于開發(fā)還是用于生產(chǎn)環(huán)境。
謹(jǐn)慎安排升級數(shù)據(jù)庫服務(wù)器。
在升級前,使用諸如PerconaToolkit中的pt-upgrade之類的工具仔細(xì)檢査系統(tǒng)。
使用InnoDB并進(jìn)行適當(dāng)?shù)呐渲茫_保InnoDB是默認(rèn)存儲引擎。如果存儲引擎被禁止,服務(wù)器就無法啟動。
確認(rèn)基本的服務(wù)器配置是正確的。
通過skip_name_resolve禁止DNS。
除非能證明有效,否則禁用査詢緩存。
避免使用復(fù)雜的特性,例如復(fù)制過濾和觸發(fā)器,除非確實需要。
監(jiān)控重要的組件和功能,特別是像磁盤空間和RAID卷狀態(tài)這樣的關(guān)鍵項目,但也要避免誤報,只有當(dāng)確實發(fā)生問題時才發(fā)送告警。
盡量記錄服務(wù)器的狀態(tài)和性能指數(shù),如果可能就盡量久地保存。
定期檢查復(fù)制完整性。
將備庫設(shè)置為只讀,不要讓復(fù)制自動啟動。
定期進(jìn)行查詢語句審査。
歸檔并清理不需要的數(shù)據(jù)。
為文件系統(tǒng)保留一些空間。在GNU/Linux中,可以使用-m選項來為文件系統(tǒng)本身保留空間。還可以在LVM卷組中留下一些空閑空間。或者,更簡單的方法,僅僅創(chuàng)建一個巨大的空文件,在文件系統(tǒng)快滿時,直接將其刪除。
養(yǎng)成習(xí)慣,評估和管理系統(tǒng)的改變、狀態(tài)以及性能信息。
我們發(fā)現(xiàn)對系統(tǒng)變更管理的缺失是所有導(dǎo)致宕機的事件中最普遍的原因。典型的錯誤包括粗心的升級導(dǎo)致升級失敗并遭遇一些Bug,或是尚未測試就將Schema或査詢語句的更改直接運行到線上,或者沒有為一些失敗的情況制定計劃,例如達(dá)到了磁盤容量限制。另外一個導(dǎo)致問題的主要原因是缺少嚴(yán)格的評估,例如因為疏忽沒有確認(rèn)備份是否是可以恢復(fù)的。最后,可能沒有正確地監(jiān)控MySQL的相關(guān)信息。例如緩存命中率報警并不能說明出現(xiàn)問題,并且可能產(chǎn)生大量的誤報,這會使監(jiān)控系統(tǒng)被認(rèn)為不太有用,于是一些人就會忽略報警。有時候監(jiān)控系統(tǒng)失效了,甚至沒人會注意到,直至你的老板質(zhì)問你,“為什么Nagios沒有告訴我們磁盤已經(jīng)滿了”。
3.2 降低平均恢復(fù)時間(MTTR)
之前提到,可以通過減少恢復(fù)時間來獲得高可用性。事實上,一些人走得更遠(yuǎn),只專注于減少恢復(fù)時間的某個方面:通過在系統(tǒng)中建立冗余來避免系統(tǒng)完全失效,并避免單點失效問題。
在降低恢復(fù)時間上進(jìn)行投資非常重要,一個能夠提供冗余和故障轉(zhuǎn)移能力的系統(tǒng)架構(gòu),則是降低恢復(fù)時間的關(guān)鍵環(huán)節(jié)。但實現(xiàn)高可用性不單單是一個技術(shù)問題,還有許多個人和組織的因素。組織和個人在避免宕機和從宕機事件中恢復(fù)的成熟度和能力層次各不相同。
團隊成員是最重要的髙可用性資產(chǎn),所以為恢復(fù)制定一個好的流程非常重要。擁有熟練技能、應(yīng)變能力、訓(xùn)練有素的雇員,以及處理緊急事件的詳細(xì)文檔和經(jīng)過仔細(xì)測試的流程,對從宕機中恢復(fù)有巨大的作用。但也不能完全依賴工具和系統(tǒng),因為它們并不能理解實際情況的細(xì)微差別,有時候它們的行為在一般情況下是正確的,但在某些場景下卻會是個災(zāi)難!
對宕機事件進(jìn)行評估有助于提升組織學(xué)習(xí)能力,可以幫助避免未來發(fā)生相似的錯誤,但是不要對“事后反思”或“事后的調(diào)査分析”期待太髙。后見之明被嚴(yán)重曲解,并且一味想找到導(dǎo)致問題的唯一根源,這可熊會影響你的判斷力。許多流行的方法,例如“五個為什么”,可能會被過度使用,導(dǎo)致一些人將他們的精力集中在找到唯一的替罪羊。很難去回顧我們解決的問題當(dāng)時所處的狀況,也很難理解真正的原因,因為原因通常是多方面的。因此,盡管事后反思可能是有用的,但也應(yīng)該對結(jié)論有所保留。即使是我們給出的建議,也是基于長期研究導(dǎo)致宕機事件的原因以及如何預(yù)防它們所得,并且只是我們的觀點而已。
這里我們要反復(fù)提醒:所有的宕機事件都是由多方面的失效聯(lián)合在一起導(dǎo)致的。因此,可以通過利用合適的方法確保單點的安全來避免。整個鏈條必須要打斷,而不僅僅是單個環(huán)節(jié)。例如,那些向我們求助恢復(fù)數(shù)據(jù)的人不僅遭受數(shù)據(jù)丟失(存儲失效,DBA誤操作等),同時還缺少一個可用的備份。
這樣說來,當(dāng)開始調(diào)査并嘗試阻止失效或加速恢復(fù)時,大多數(shù)人和組織不應(yīng)太過于內(nèi)疚,而是要專注于技術(shù)上的一些措施——特別是那些很酷的方法,例如集群系統(tǒng)和冗余架構(gòu)。這些是有用的,但要記住這些系統(tǒng)依然會失效。事實上,有一種MMM復(fù)制管理,雖然它被證明可能導(dǎo)致更多宕機時間。你應(yīng)該不會奇怪一組Perl腳本會陷于混亂,但即使是特別昂貴并精密設(shè)計的系統(tǒng)也會出現(xiàn)災(zāi)難性的失效——是的,即使是花費了大量金錢的SAN也是如此。我們已經(jīng)見過太多的SAN失效。
4.避免單點失效
找到并消除系統(tǒng)中的可能失效的單點,并結(jié)合切換到備用組件的機制,這是一種通過減少恢復(fù)時間(MTTR)來改善可用性的方法。如果你夠聰明,有時候甚至能將實際的恢復(fù)時間降低至0,但總的來說這很困難。(即使一些非常引人注目的技術(shù),例如昂貴的負(fù)載均衡器,在發(fā)現(xiàn)問題并進(jìn)行反饋時也會導(dǎo)致一定的延遲。)
思考并梳理整個應(yīng)用,嘗試去定位任何可能失效的單點。是一個硬盤驅(qū)動器,一臺服務(wù)器,一臺交換或路由器,還是某個機架的電源?所有數(shù)據(jù)都在一個數(shù)據(jù)中心,或者冗余數(shù)據(jù)中心是由同一個公司提供的嗎?系統(tǒng)中任何不冗余的部分都是一個可能失效的單點。其他比較普遍的單點失效依賴于一些服務(wù),例如DNS、單一網(wǎng)絡(luò)提供商、單個云“可用區(qū)域”,以及單個電力輸送網(wǎng),具體有哪些取決于你的關(guān)注點。
單點失效并不總是能夠消除。增加冗余或許也無法做到,因為有些限制無法避開,例如地理位置,預(yù)算,或者時間限制等。試著去理解每一個影響可用性的部分,采取一種平衡的觀點來看待風(fēng)險,并首先解決其中影響最大的那個。一些人試圖編寫一個軟件來處理所有的硬件失效,但軟件本身導(dǎo)致的宕機時間可能比它節(jié)約的還要多。也有人想建立一種“永不沉沒”的系統(tǒng),包括各種冗余,但他們忘記了數(shù)據(jù)中心可能掉電或失去連接。或許他們徹底忘記了惡意攻擊者和程序錯誤的可能性,這些情況可能會刪除或損壞數(shù)據(jù)--個不小心執(zhí)行的DROPTABLE也會產(chǎn)生宕機時間。
可以采用兩種方法來為系統(tǒng)增加冗余:增加空余容量和重復(fù)組件。增加容量余量通常很簡單——可以使用本章或前一章討論的任何技術(shù)。一個提升可用性的方法是創(chuàng)建一個集群或服務(wù)器池,并使用負(fù)載均衡解決方案。如果一臺服務(wù)器失效,其他服務(wù)器可以接管它的負(fù)載。有些人有意識地不使用組件的全部能力,這樣可以保留一些“動態(tài)余量”來處理因為負(fù)載增加或組件失效導(dǎo)致的性能問題。
出于很多方面的考慮會需要冗余組件,并在主要組件失效時能有一個備件來隨時替換。冗余組件可以是空閑的網(wǎng)卡、路由器或者硬盤驅(qū)動器——任何能想到的可能失效的東西。完全冗余MySQL服務(wù)器可能有點困難,因為一個服務(wù)器在沒有數(shù)據(jù)時毫無用處。這意味著你必須確保備用服務(wù)器能夠獲得主服務(wù)器上的數(shù)據(jù)。共享或復(fù)制存儲是一個比較流行的辦法,但這真的是一個高可用性架構(gòu)嗎?讓我們深入其中看看。
4.1 共享存儲或磁盤復(fù)制
共享存儲能夠為數(shù)據(jù)庫服務(wù)器和存儲解耦合,通常使用的是SAN。使用共享存儲時,服務(wù)器常掛載文件系統(tǒng)并進(jìn)行操作。如果服務(wù)器掛了,備用服務(wù)器可以掛載相同的文件系統(tǒng),執(zhí)行需要的恢復(fù)操作,并在失效服務(wù)器的數(shù)據(jù)上啟動MySQL。這個過程在邏輯上跟修復(fù)那臺故障的服務(wù)器沒什么兩樣,不過更快速,因為備用服務(wù)器已經(jīng)啟動,隨時可以運行。當(dāng)開始故障轉(zhuǎn)移時,檢査文件系統(tǒng)、恢復(fù)InnoDB以及預(yù)熱,最有可能遇到延遲的地方,但檢測失效本身在許多設(shè)置中也會花費很長時間。
共享存儲有兩個優(yōu)點:可以避免除存儲外的其他任何組件失效所引起的數(shù)據(jù)丟失,并為非存儲組件建立冗余提供可能。因此它有助于減少系統(tǒng)一些部分的可用性需求,這樣就可以集中精力關(guān)注一小部分組件來獲得高可用性。不過,共享存儲本身仍是可能失效的單點。如果共享存儲失效了,那整個系統(tǒng)也失效了,盡管SAN通常設(shè)計良好,但也可能失效,有時候需要特別關(guān)注。就算SAN本身擁有冗余也會失效。
共享存儲本身也有風(fēng)險,如果MySQL崩潰等故障導(dǎo)致數(shù)據(jù)文件損壞,可能會導(dǎo)致備用服務(wù)器無法恢復(fù)。我們強烈建議在使用共享存儲策略時選擇Innodb存儲引擎或其他穩(wěn)定的ACID存儲引擎。一次崩潰幾乎肯定會損壞MyISAM表,需要花費很長時間來修復(fù),并且會丟失數(shù)據(jù)。我們也強烈建議使用日志型文件系統(tǒng)。我們見過比較嚴(yán)重的情況是,使用非日志型文件系統(tǒng)和SAN(這是文件系統(tǒng)的問題,跟SAN無關(guān))導(dǎo)致數(shù)據(jù)損壞無法恢復(fù)。
磁盤復(fù)制技術(shù)是另外一個獲得跟SAN類似效果的方法。MySQL中最普遍使用的磁盤復(fù)制技術(shù)是DRBD,并結(jié)合Linux-HA項目中的工具使用(后面會介紹到)。
DRBD是一個以Linux內(nèi)核模塊方式實現(xiàn)的塊級別同步復(fù)制技術(shù)。它通過網(wǎng)卡將主服務(wù)器的每個塊復(fù)制到另外一個服務(wù)器的塊設(shè)備上(備用設(shè)備),并在主設(shè)備提交塊之前記錄下來由于在備用DRBD設(shè)備上的寫入必須要在主設(shè)備上的寫入完成之前,因此備用設(shè)備的性能至少要和主設(shè)備一樣,否則就會限制主設(shè)備的寫入性能。同樣,如果正在使用DRBD磁盤復(fù)制技術(shù)以保證在主設(shè)備失效時有一個可隨時替換的備用設(shè)備,備用服務(wù)器的硬件應(yīng)該跟主服務(wù)器的相匹配。帶電池寫緩存的RAID控制器對DRBD而言幾乎是必需的,因為在沒有這樣的控制器時性能可能會很差。
如果主服務(wù)器失效,可以把備用設(shè)備提升為主設(shè)備。因為DRBD是在磁盤塊層進(jìn)行復(fù)制,而文件系統(tǒng)也可能會不一致。這意味著最好是使用日志型文件系統(tǒng)來做快速恢復(fù)。一旦設(shè)備恢復(fù)完成,MySQL還需要運行自身的恢復(fù)。原故障服務(wù)器恢復(fù)后,會與新的主設(shè)備進(jìn)行同步,并假定自身角色為備用設(shè)備。
從如何實際地實現(xiàn)故障轉(zhuǎn)移的角度來看,DRBD和SAN很相似:有一個熱備機器,開始提供服務(wù)時會使用和故障機器相同的數(shù)據(jù)。最大的不同是,DRBD是復(fù)制存儲——不是共享存儲——所以當(dāng)使用DRBD時,獲得的是一份復(fù)制的數(shù)據(jù),而SAN則是使用與故障機器同一物理設(shè)備上的相同數(shù)據(jù)副本。換句話說,磁盤復(fù)制技術(shù)的數(shù)據(jù)是冗余的,所以存儲和數(shù)據(jù)本身都不會存在單點失效問題。這兩種情況下,當(dāng)啟動備用機器時,MySQL服務(wù)器的緩存都是空的。相比之下,備庫的緩存至少是部分預(yù)熱的。
DRBD有一些很好的特性和功能,可以防止集群軟件普遍會遇到的一些問題。一個典型 的例子是“腦裂綜合征”,在兩個節(jié)點同時提升自己為主服務(wù)器時會發(fā)生這種問題。可以通過配置DRBD來防止這種事件發(fā)生。但是DRBD也不是一個能滿足所有需求的完美解決方案。我們來看看它有哪些缺點:
DRBD的故障轉(zhuǎn)移無法做到秒級以內(nèi)。它通常至少需要幾秒鐘時間來將備用設(shè)備提升成主設(shè)備,這還不包括任何必要的文件系統(tǒng)恢復(fù)和MySQL恢復(fù)。
它很昂貴,因為必須在主動一被動模式下運行。熱備服務(wù)器的復(fù)制設(shè)備因為處于被動模式,無法用于其他任務(wù)。當(dāng)然這是不是缺點取決于看問題的角度。如果你希望獲得真正的髙可用性并且在發(fā)生故障時不能容忍服務(wù)降級,就不應(yīng)該在一臺機器上運行兩臺服務(wù)器的負(fù)載量,因為如果這么做了,當(dāng)其中一臺發(fā)生故障時,就無法處理這些負(fù)載了。可以用這些備用服務(wù)器做一些其他用途,例如用作備庫,但還是會有一些資源浪費。
對于MyISAM表實際上用處不大,因為MyISAM表崩潰后需要花費很長時間來檢査和修復(fù)。對任何期望獲得高可用性的系統(tǒng)而言,MyISAM都不是一個好選擇;請使用InnoDB或其他支持快速、安全恢復(fù)的存儲引擎來代替MyISAM。
DRBD無法代替?zhèn)浞荨H绻疟P由于蓄意的破壞、誤操作、Bug或者其他硬件故障導(dǎo)致數(shù)據(jù)損壞,DRBD將無濟于事。此時復(fù)制的數(shù)據(jù)只是被損壞數(shù)據(jù)的完美副本。你需要使用備份(或MySQL延時復(fù)制)來避免這些問題。
對寫操作而言增加了負(fù)擔(dān)。具體會增加多少負(fù)擔(dān)呢?通常可以使用百分比來表示,但這并不是一個好的度量方法。你需要理解寫入時增加的延遲主要由網(wǎng)絡(luò)往返開銷和遠(yuǎn)程服務(wù)器存儲導(dǎo)致,特別是對于小的寫入而言延遲會更大。盡管增加的延遲可能也就0.3ms,這看起來比在本地磁盤上I/O的4?10ms的延遲要小很多,但卻是正常的帶有寫緩存的RAID控制器的延遲的3?4倍=使用DRBD導(dǎo)致服務(wù)器變慢最常見的原因是MySQL使用InnoDB并采取了完全持久化模式,這會導(dǎo)致許多小的寫入和fsync()調(diào)用,通過DRBD同步時會非常慢。
我們傾向于只使用DRBD復(fù)制存放二進(jìn)制日志的設(shè)備。如果主動節(jié)點失效,可以在被動節(jié)點上開啟一個日志服務(wù)器,然后對失效主庫的所有備庫應(yīng)用這些二進(jìn)制日志。接下來可以選擇其中一個備庫提升為主庫,以代替失效的系統(tǒng)。
說到底,共享存儲和磁盤復(fù)制與其說是高可用性(低宕機時間)解決方案,不如說是一種保證數(shù)據(jù)安全的方法。只要擁有數(shù)據(jù),就可以從故障中恢復(fù),并且比無法恢復(fù)的情況的MTTR更低。(即使是很長的恢復(fù)時間也比不能恢復(fù)要快。)但是相比于備用服務(wù)器啟動并一直運行的架構(gòu),大多數(shù)共享存儲或磁盤復(fù)制架構(gòu)會增加MTTR。有兩種啟用備用設(shè)備并運行的方法:以及接下來會討論的同步復(fù)制。
討論:主動一主動訪問模式的共享存儲怎么樣?
在一個SAN、NAS或者集群文件系統(tǒng)上以主動一主動模式運行多個實例怎么樣?MySQL不能這么做。因為MySQL并沒有被設(shè)計成和其他MySQL實例同步對數(shù)據(jù)的訪問,所以無法在同一份數(shù)據(jù)上開啟多個MySQL實例。(如果在一份只讀的靜態(tài)數(shù)據(jù)上使用MyISAM,技術(shù)上是可行的,但我們還沒有見過任何實際的應(yīng)用。)
MySQL的一個名為ScaleDB的存儲引擎在底層提供了操作共享存儲的API,但我們還沒有評估過,也沒有見過任何生產(chǎn)環(huán)境使用。在mysql5.5發(fā)布時時它還是beta版。
4.2 MySQL同步復(fù)制
當(dāng)使用同步復(fù)制時,主庫上的事務(wù)只有在至少一個備庫上提交后才能認(rèn)為其執(zhí)行完成。這實現(xiàn)了兩個目標(biāo):當(dāng)服務(wù)器崩潰時沒有提交的事務(wù)會丟失,并且至少有一個備庫擁有實時的數(shù)據(jù)副本。大多數(shù)同步復(fù)制架構(gòu)運行在主動-主動模式。這意味著每個服務(wù)器在任何時候都是故障轉(zhuǎn)移的候選者,這使得通過冗余獲得高可用性更加容易。
1.MySQLCluster
MySQL中的同步復(fù)制首先出現(xiàn)在MySQLCluster(NDBCluster)。它在所有節(jié)點上進(jìn)行同步的主-主復(fù)制。這意味著可以在任何節(jié)點上寫入;這些節(jié)點擁有等同的讀寫能力。每一行都是冗余存儲的,這樣即使丟失了一個節(jié)點,也不會丟失數(shù)據(jù),并且集群仍然能提供服務(wù)。盡管MySQLCluster還不是適用于所有應(yīng)用的完美解決方案,但正如我們在前一章提到的,在最近的版本中它做了非常快速的改進(jìn),現(xiàn)在已經(jīng)擁有大量的新特性和功能:非索引數(shù)據(jù)的磁盤存儲、增加數(shù)據(jù)節(jié)點能夠在線擴展、使用ndbinfo表來管理集群、配置和管理集群的腳本、多線程操作、下推(push-down)的關(guān)聯(lián)操作(現(xiàn)在稱為自適應(yīng)查詢本地化)、能夠處理BLOB列和很多列的表、集中式的用戶管理,以及通過像memcached協(xié)議一樣的NDBAPI來實現(xiàn)NoSQL訪問。在下一個版本中將包含最終一致運行模式,包括為跨數(shù)據(jù)中心的主動-主動復(fù)制提供事務(wù)沖突檢測和跨WAN解決方案。簡而言之,MySQLCluster是一項引人注目的技術(shù)。
現(xiàn)在至少有兩個為簡化集群部署和管理提供附加產(chǎn)品的供應(yīng)商:Oracle針對MySQL Cluster的服務(wù)支持包含了MySQLClusterManager工具;Severalnines提供了ClusterControl工具,該工具還能夠幫助部署和管理復(fù)制集群。
2.PerconaXtraDBCluster
PerconaXtraDBCluster是一個相對比較新的技術(shù),基于已有的XtraDB(InnoDB)存儲
引擎增加了同步復(fù)制和集群特性,而不是通過一個新的存儲引擎或外部服務(wù)器來實現(xiàn)。它是基于Galera(支持在集群中跨節(jié)點復(fù)制寫操作)實現(xiàn)的,這是一個在集群中不同節(jié)點復(fù)制寫操作的庫。跟MySQLCluster類似,PerconaXtraDBCluster提供同步多主庫復(fù)制,支持真正的任意節(jié)點寫入能力,能夠在節(jié)點失效時保證數(shù)據(jù)零丟失(持久性,ACID中的D),另外還提供高可用性,在整個集群沒有失效的情況下,就算單個節(jié)點失效也沒有關(guān)系。
Galera作為底層技術(shù),使用一種被稱為寫入集合(write-set)復(fù)制的技術(shù)。寫入集合實際上被作為基于行的二進(jìn)制日志事件進(jìn)行編碼,目的是在集群中的節(jié)點間傳輸并進(jìn)行更新,但是這不要求二進(jìn)制日志是打開的。
PerconaXtraDBCluster的速度很快。跨節(jié)點復(fù)制實際上比沒有集群還要快,因為在完全持久性模式下,寫入遠(yuǎn)程RAM比寫入本地磁盤要快。如果你愿意,可以選擇通過降低每個節(jié)點的持久性來獲得更好的性能,并且可以依賴于多個節(jié)點上的數(shù)據(jù)副本來獲得持久性。NDB也是基于同樣的原理實現(xiàn)的。集群在整體上的持久性并沒有降低;僅僅是降低了本地節(jié)點的持久性。除此之外,還支持行級別的并發(fā)(多線程)復(fù)制,這樣就可以利用多個CPU核心來執(zhí)行寫入集合。這些特性結(jié)合起來使得PerconaXtraDBCluster非常適合云計算環(huán)境,因為云計算環(huán)境中的CPU和磁盤通常比較慢。
在集群中通過設(shè)置auto_increment_offset和auto_increment_increment來實現(xiàn)自增鍵,以使節(jié)點間不會生成沖突的主鍵值。鎖機制和標(biāo)準(zhǔn)InnoDB完全相同,使用的是樂觀并發(fā)控制。當(dāng)事務(wù)提交時,所有的更新是序列化的,并在節(jié)點間傳輸,同時還有一個檢測過程,以保證一旦發(fā)生更新沖突,其中一些更新操作需要丟棄。這樣如果許多節(jié)點同時修改同樣的數(shù)據(jù),可能產(chǎn)生大量的死鎖和回滾。
PerconaXtraDBCluster只要集群內(nèi)在線的節(jié)點數(shù)不少于“法定人數(shù)(quorum)”就能保證服務(wù)的高可用性。如果發(fā)現(xiàn)某個節(jié)點不屬于“法定人數(shù)”中的一員,就會從集群中將其踢出。被踢出的節(jié)點在再次加入集群前必須重新同步。因此集群也無法處理“腦裂綜合征”;如果出現(xiàn)腦裂則集群會停止服務(wù)。在一個只有兩個節(jié)點的集群中,如果其中一個節(jié)點失效,剩下的一個節(jié)點達(dá)不到“法定人數(shù)”,集群將停止服務(wù),所以實際上最少需要三個節(jié)點才能實現(xiàn)高可用的集群。
PerconaXtraDBCluster有許多優(yōu)點:
提供了基于InnoDB的透明集群,所以無須轉(zhuǎn)換到另外的技術(shù),例如NDB這樣完全不同的技術(shù)需要很多學(xué)習(xí)成本和管理。
提供了真正的高可用性,所有節(jié)點等效,并在任何時候提供讀寫服務(wù)。相比較而言,MySQL內(nèi)建的異步復(fù)制和半同步復(fù)制必須要有一個主庫,并且不能保證數(shù)據(jù)被復(fù)制到備庫,也無法保證備庫數(shù)據(jù)是最新的并能夠隨時提升為主庫。
節(jié)點失軟時保證數(shù)據(jù)不丟失。實際上,由于所有的節(jié)點都擁有全部數(shù)據(jù),因此可以丟失任意一個節(jié)點而不會丟失數(shù)據(jù)(即使集群出現(xiàn)腦裂并停止工作)。這和NDB不同,NDB通過節(jié)點組進(jìn)行分區(qū),當(dāng)在一個節(jié)點組中的所有服務(wù)器失效時就可能丟失數(shù)據(jù)。
備庫不會延遲,因為在事務(wù)提交前,寫入集合已經(jīng)在集群的所有節(jié)點上傳播并被確認(rèn)了。
因為是使用基于行的日志事件在備庫上進(jìn)行更新,所以執(zhí)行寫入集合比直接執(zhí)行更新的開銷要小很多,就和使用基于行的復(fù)制差不多。當(dāng)結(jié)合多線程應(yīng)用的寫入集合時,可以使其比MySQL本身的復(fù)制更具備可擴展性。
當(dāng)然我們也需要提及Percona
XtraDB Cluster的一些缺點:
它很新,因此還沒有足夠的經(jīng)驗來證明其優(yōu)點和缺點,也缺乏合適的使用案例。
整個集群的寫入速度由最差的節(jié)點決定。因此所有的節(jié)點最好擁有相同的硬件配置,如果一個節(jié)點慢下來(例如,RAID卡做了一次battery-learn循環(huán)),所有的節(jié)點都會慢下來。如果一個節(jié)點接收寫入操作變慢的可能性為P,那么有3個節(jié)點的集群變慢的可能性為3P。
沒有NDB那樣節(jié)省空間,因為每個節(jié)點都需要保存全部數(shù)據(jù),而不是僅僅一部分。但另一方面,它基于Percona XtraDB (InnoDB的增強版本),也就沒有NDB關(guān)于磁盤數(shù)據(jù)限制的擔(dān)憂。
當(dāng)前不支持一些在異步復(fù)制中可以做的操作,例如在備庫上離線修改schema,然后將其提升為主庫,然后在其他節(jié)點上重復(fù)離線修改操作。當(dāng)前可替代的選擇是使用諸如PerconaToolkit中的在線schema修改工具。不過滾動式schema升級(rollingschemaupgrade)也發(fā)布。
當(dāng)向集群中增加一個新節(jié)點時,需要復(fù)制所有的數(shù)據(jù),還需要跟上不斷進(jìn)行的寫入操作,所以一個擁有大量寫入的大型集群很難進(jìn)行擴容。這實際上限制了集群的數(shù)據(jù)大小。我們無法確定具體的數(shù)據(jù)。但悲觀地估計可能低至100GB或更小,也可能會大得多。這一點需要時間和經(jīng)驗來證明。
復(fù)制協(xié)議在寫入時對網(wǎng)絡(luò)波動比較敏感,這可能導(dǎo)致節(jié)點停止并從集群中踢出。所以我們推薦使用高性能網(wǎng)絡(luò),另外還需要很好的冗余。如果沒有可靠的網(wǎng)絡(luò),可能會導(dǎo)致需要頻繁地將節(jié)點加入到集群中。這需要重新同步數(shù)據(jù)。有一個幾乎接近可用的特性,即通過增量狀態(tài)傳輸來避免完全復(fù)制數(shù)據(jù)集,因此未來這并不是一個問題。還可以配置Galera以容忍更大的網(wǎng)絡(luò)延遲(以延遲故障檢測為代價),另外更加可靠的算法也計劃在未來的版本中實現(xiàn)。
如果沒有仔細(xì)關(guān)注,集群可能會增長得太大,以至于無法重啟失效節(jié)點,就像在一個合理的時間范圍內(nèi),如果在日常工作中沒有定期做恢復(fù)演練,備份也會變得太過龐大而無法用于恢復(fù)。我們需要更多的實踐經(jīng)驗來了解它事實上是如何工作的。
由于在事務(wù)提交時需要進(jìn)行跨節(jié)點通信,寫入會更慢,隨著集群中增加的節(jié)點越來越多,死鎖和回滾也會更加頻繁。(參閱前一章了解為什么會發(fā)生這種情況。)
Percona XtraDB
Cluster和Galera都處于其生命周期的早期,正在被快速地修改和改進(jìn)。在mysql5.5發(fā)布時,正在進(jìn)行或即將進(jìn)行的改進(jìn)包括群體行為、安全性、同步性、內(nèi)存管理、狀態(tài)轉(zhuǎn)移等。未來還可以為離線節(jié)點執(zhí)行諸如滾動式schema變更的操作。
4.3 基于復(fù)制的冗余
復(fù)制管理器是使用標(biāo)準(zhǔn)MySQL復(fù)制來創(chuàng)建冗余的工具。盡管可以通過復(fù)制來改善可用性,但也有一些“玻璃天花板”會阻止MySQL當(dāng)前版本的異步復(fù)制和半同步復(fù)制獲得和真正的同步復(fù)制相同的結(jié)果。復(fù)制無法保證實時的故障轉(zhuǎn)移和數(shù)據(jù)零丟失,也無法將所有節(jié)點等同對待。
復(fù)制管理器通常監(jiān)控和管理三件事:應(yīng)用和MySQL間的通信、MySQL服務(wù)器的健康度,以及MySQL服務(wù)器間的復(fù)制關(guān)系。它們既可以修改負(fù)載均衡的配置,也可以在必要的時候轉(zhuǎn)移虛擬IP地址以使應(yīng)用連接到合適的服務(wù)器上,還能夠在一個偽集群中操縱復(fù)制以選擇一個服務(wù)器作為寫入節(jié)點。大體上操作并不復(fù)雜:只需要確定寫入不會發(fā)送到一個還沒有準(zhǔn)備好提供寫服務(wù)的服務(wù)器上,并保證當(dāng)需要提升一臺備庫為主庫時記錄下正確的復(fù)制坐標(biāo)。
這聽起來在理論上是可行的,但我們的經(jīng)驗表明實際上并不總是能有效工作。事實上這非常糟糕,有些時候最好有一些輕量級的工具集來幫助從常見的故障中恢復(fù)并以很少的開銷獲得較髙的可用性。不幸的是,在mysql5.5時還沒有聽說任何一個好的工具集可以可靠地完成這一點。稍后我們會介紹兩個復(fù)制管理器,其中一個很新,而另外一個則有很多問題。
我們發(fā)現(xiàn)很多人試圖去寫自己的復(fù)制管理器。他們常常會陷入很多人已經(jīng)遭遇過的陷阱。自己去寫一個復(fù)制管理器并不是好主意。異步組件有大量的故障形式,很多你從未親身經(jīng)歷過,其中一些甚至無法理解,并且程序也無法適當(dāng)處理,因此從這些異步組件中得到正確的行為相當(dāng)困難,并且可能遭遇數(shù)據(jù)丟失的危險。事實上,機器剛開始出現(xiàn)問題時,由一個經(jīng)驗豐富的人來解決是很快的,但如果其他人做了一些錯誤的修復(fù)操作則可能導(dǎo)致問題更嚴(yán)重。
我們要提到的第一個復(fù)制管理器是MMM,本書的作者對于該工具集是否適用于生產(chǎn)環(huán)境部署的意見并不一致(盡管該工具的原作者也承認(rèn)它并不可靠)。我們中有些人認(rèn)為它在一些人工一故障轉(zhuǎn)移模式下的場景中比較有用,而有些人甚至從不便用這個工具。我們的許多客戶在自動一故障轉(zhuǎn)移模式下使用該工具時確實遇到了許多嚴(yán)重的問題。它會導(dǎo)致健康的服務(wù)器離線,也可能將寫入發(fā)送到錯誤的地點,并將備庫移動到錯誤的坐標(biāo)。有時混亂就接踵而至。
另外一個比較新一點的工具是YoshinoriMatsunobu的MHA工具集。它和MMM—樣是一組腳本,使用相同的通用技術(shù)來建立一個偽集群,但它不是一個完全的替換者,它不會去做太多的事情,并且依賴干Pacemaker來轉(zhuǎn)移虛擬IP地址。一個主要的不同是,MHA有一個很好的測試集,可以防止一些MMM遇到過的問題。除此之外,我們對該工具集還沒有更多的認(rèn)識,我們只和Yoshinori討論過,但還沒有真正使用過。
基于復(fù)制的冗余最終來說好壞參半。只有在可用性的重要性遠(yuǎn)比一致性或數(shù)據(jù)零丟失保
證更重要時才推薦使用。例如,一些人并不會真的從他們的網(wǎng)站功能中獲利,而是從它的可用性中賺錢。誰會在乎是否出現(xiàn)了故障導(dǎo)致一張照片丟失了幾條評論或其他什么東西呢?只要廣告收益繼續(xù)滾滾而來,可能并不值得花更多成本去實現(xiàn)真正的高可用性。但還是可以通過復(fù)制來建立“盡可能的”高可用性,當(dāng)遇到一些很難處理的嚴(yán)重宕機時可能會有所幫助。這是一個大賭注,并且可能對大多數(shù)人而言太過于冒險,除非是那些老成(或者專業(yè))的用戶。
問題是許多用戶不知道如何去證明自己有資格并評估復(fù)制“輪盤賭”是否適合他們。這
有兩個方面的原因。第一,他們并沒有看到“玻璃天花板”,錯誤地認(rèn)為一組虛擬IP地址、復(fù)制以及管理腳本能夠?qū)崿F(xiàn)真正的髙可用性。第二,他們低估了技術(shù)的復(fù)雜度,因此也低估了嚴(yán)重故障發(fā)生后從中恢復(fù)的難度。一些人認(rèn)為他們能夠使用基于復(fù)制的冗余技術(shù),但隨后他們可能會更希望選擇一個有更強保障的簡單系統(tǒng)。
其他一些類型的復(fù)制,例如DRBD或者SAN,也有它們的缺點——請不要認(rèn)為我們將這些技術(shù)說得無所不能而把MySQL自身的復(fù)制貶得一團糟,那不是我們的本意。你可以為DRBD寫出低質(zhì)量的故障轉(zhuǎn)移腳本,這很簡單,就像為MySQL復(fù)制編寫腳本一樣。主要的區(qū)別是MySQL復(fù)制非常復(fù)雜,有很多非常細(xì)小的差別,并且不會阻止你干壞事。
5.故障轉(zhuǎn)移和故障恢復(fù)
冗余是很好的技術(shù),但實際上只有在遇到故障需要恢復(fù)時才會用到。(見鬼,這可以用備份來實現(xiàn))。冗余一點兒也不會增加可用性或減少宕機。在故障轉(zhuǎn)移的過程中,高可用性是建立在冗余的基礎(chǔ)上。當(dāng)有一個組件失效,但存在冗余時,可以停止使用發(fā)生故障的組件,而使用冗余備件。冗余和故障轉(zhuǎn)移結(jié)合可以幫助更快地恢復(fù),如你所知,MTTR的減少將降低宕機時間并改善可用性。
在繼續(xù)這個話題之前,我們先來定義一些術(shù)語。我們統(tǒng)一使用“故障轉(zhuǎn)移(failover)”,有些人使用“回退”(fallback)表達(dá)同一意思。有時候也有人說“切換(switchover)”,以表明一次計劃中的切換而不是故障后的應(yīng)對措施。我們也會使用“故障恢復(fù)”來表示故障轉(zhuǎn)移的反面。如果系統(tǒng)擁有故障恢復(fù)能力,故障轉(zhuǎn)移就是一個雙向過程:當(dāng)服務(wù)器A失效,服務(wù)器B代替它,在修復(fù)服務(wù)器A后可以再替換回來。
故障轉(zhuǎn)移比僅僅從故障中恢復(fù)更好。也可以針對一些情況制訂故障轉(zhuǎn)移計劃,例如升級、schema變更、應(yīng)用修改,或者定期維護,當(dāng)發(fā)生故障時可以根據(jù)計劃進(jìn)行故障轉(zhuǎn)移來減少宏機時間(改善可用性)。
你需要確定故障轉(zhuǎn)移到底需要多快,也要知道在一次故障轉(zhuǎn)移后替換一個失效組件應(yīng)該多快。在你恢復(fù)系統(tǒng)耗盡的備件容量之前,會出現(xiàn)冗余不足,并面臨額外風(fēng)險。因此,擁有一個備件并不能消除即時替換失效組件的需求。構(gòu)建一個新的備用服務(wù)器,安裝操作系統(tǒng),并復(fù)制數(shù)據(jù)的最新副本,可以多快呢?有足夠的備用機器嗎?你可能需要不止一臺以上。
故障轉(zhuǎn)移的緣由各不相同。我們已經(jīng)討論了其中的一些,因為負(fù)載均衡和故障轉(zhuǎn)移在很多方面很相似,它們之間的分界線比較模糊。總的來說,我們認(rèn)為一個完全的故障轉(zhuǎn)移解決方案至少能夠監(jiān)控并自動替換組件。它對應(yīng)用應(yīng)該是透明的。負(fù)載均衡不需要提供這些功能。
在UNIX領(lǐng)域,故障轉(zhuǎn)移常常使用HighAvailabilityLinux項目提供的工具來完成,該項目可在許多類UNIX系統(tǒng)上運行,而不僅僅是Linux。Linux-HA棧在最近幾年明顯多了很多新特性。現(xiàn)在大多數(shù)人認(rèn)為Pacemaker是棧中的一個主要組件。Pacemaker替代了老的心跳工具。還有其他一些工具實現(xiàn)了IP托管和負(fù)載均衡功能。可以將它們跟DRBD和/或者LVS結(jié)合起來使用。
故障轉(zhuǎn)移最重要的部分就是故障恢復(fù)。如果服務(wù)器間不能自如切換,故障轉(zhuǎn)移就是一個死胡同,只能是延緩宕機時間而已。這也是我們傾向于對稱復(fù)制布局,例如雙主配置,而不會選擇使用三臺或更多的聯(lián)合主庫(co-master)來進(jìn)行環(huán)形復(fù)制的原因。如果配置是對等的,故障轉(zhuǎn)移和故障恢復(fù)就是在相反方向上的相同操作。(值得一提的是DRBD具有內(nèi)建的故障恢復(fù)功能。)
在一些應(yīng)用中,故障轉(zhuǎn)移和故障恢復(fù)需要盡量快速并具備原子性。即便這不是決定性的,不依靠那些不受你控制的東西也依然是個好主意,例如DNS變更或者應(yīng)用程序配置文件。一些問題直到系統(tǒng)變得更加龐大時才會顯現(xiàn)出來,例如當(dāng)應(yīng)用程序強制重啟以及原子性需求出現(xiàn)時。
由于負(fù)載均衡和故障轉(zhuǎn)移兩者聯(lián)系較緊密,有些硬件和軟件是同時為這兩個目的設(shè)計的,因此我們建議所選擇的任何負(fù)載均衡技術(shù)應(yīng)該都提供故障轉(zhuǎn)移功能。這也是我們建議避免使用DNS和修改代碼來做負(fù)載均衡的真實原因。如果為負(fù)載均衡采用了這些策略,就需要做一些額外的工作:當(dāng)需要高可用性時,不得不重寫受影響的代碼。
以下小節(jié)討論了一些比較普遍的故障轉(zhuǎn)移技術(shù)。可以手動執(zhí)行或使用工具來實現(xiàn)。
5.1 提升備庫或切換角色
提升一臺備庫為主庫,或者在一個主一主復(fù)制結(jié)構(gòu)中調(diào)換主動和被動角色,這些都是許多MySQL故障轉(zhuǎn)移策略很重要的一部分。正如本章之前提到的,我們不能認(rèn)定自動化工具總能在所有的情況下做正確的事情——或者至少以我們的名譽擔(dān)保沒有這樣的工具。
你不應(yīng)該假定在發(fā)生故障時能夠立刻切換到被動備庫,這要看具體的工作負(fù)載。備庫會重放主庫的寫入,但如果不用來提供讀操作,就無法進(jìn)行預(yù)熱來為生產(chǎn)環(huán)境負(fù)載提供服務(wù)。如果希望有一個隨時能承擔(dān)讀負(fù)載的備庫,就要不斷地“訓(xùn)練”它,既可以將其用于分擔(dān)工作負(fù)載,也可以將生產(chǎn)環(huán)境的讀査詢鏡像到備庫上。我們有時候通過監(jiān)聽TCP流量,截取出其中的SELECT査詢,然后在備庫上重放來實現(xiàn)這個目的。PerconaToolkit中有一些工具可以做到這一點。
5.2 虛擬IP地址或IP接管
可以為需要提供特定服務(wù)的MySQL實例指定一個邏輯IP地址。當(dāng)MySQL實例失效時,可以將IP地址轉(zhuǎn)移到另一臺MySQL服務(wù)器上。這和我們在前一章提到的思想本質(zhì)上是相同的,唯一的不同是現(xiàn)在是用于故障轉(zhuǎn)移,而不是負(fù)載均衡。
這種方法的好處是對應(yīng)用透明。它會中斷已有的連接,但不要求修改配置。有時候還可以原子地轉(zhuǎn)移IP地址,保證所有的應(yīng)用在同一時間看到這一變更。當(dāng)服務(wù)器在可用和不可用狀態(tài)間“搖擺”時,這一點尤其重要。
以下是它的一些不足之處:
需要把所有的IP地址定義在同一網(wǎng)段,或者使用網(wǎng)絡(luò)橋接。
改變IP地址需要系統(tǒng)root權(quán)限。
有時候還需要更新ARP緩存。有些網(wǎng)絡(luò)設(shè)備可能會把ARP信息保存太久,以致無法即時將一個IP地址切換到另一個MAC地址上。我們看到過很多網(wǎng)絡(luò)設(shè)備或其他組件不配合切換的例子,結(jié)果系統(tǒng)的許多部分可能無法確定IP地址到底在哪里。
需要確定網(wǎng)絡(luò)硬件支持快速IP接管。有些硬件需要克隆MAC地址后才能工作。
有些服務(wù)器即使完全喪失功能也會保持持有IP地址,所以可能需要從物理上關(guān)閉或斷開網(wǎng)絡(luò)連接。這就是為人所熟知的“擊中其他節(jié)點的頭部”(shoottheothernodeinthehead,簡稱STONITH)。它還有一個更加微妙并且比較官方的名字:擊劍(fencing) 。
浮動IP地址和IP接管能夠很好地應(yīng)付彼此臨近(也就是在同一子網(wǎng)內(nèi))的機器之間的故障轉(zhuǎn)移。但是最后需要提醒的是,這種策略并不總是萬無一失,還取決于網(wǎng)絡(luò)硬件等因素。
討論:等待更新擴散
經(jīng)常有這種情況,在某一層定義了一個冗余后,需要等待低層執(zhí)行一些改變。在本章前面的篇幅里,我們指出通過DNS修改服務(wù)器是一個很脆弱的解決方案,因為DNS的更新擴散速度很慢,改變IP地址可給予你更多的控制,但在一個LAN中的IP地址同樣依賴于更低層——ARP——來擴散更新。
5.3 中間件解決方案
可以使用代理、端口轉(zhuǎn)發(fā)、網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)或者硬件負(fù)載均衡來實現(xiàn)故障轉(zhuǎn)移和故障恢復(fù)。這些都是很好的解決方案,不像其他方法可能會引入一些不確定性(所有系統(tǒng)組件認(rèn)同哪一個是主庫嗎?它能夠及時并原子地更改嗎?),它們是控制應(yīng)用和服務(wù)器間連接的中樞。但是,它們自身也引入了單點失效,需要準(zhǔn)備冗余來避免這個問題。
使用這樣的解決方案,你可以將一個遠(yuǎn)程數(shù)據(jù)中心設(shè)置成看起來好像和應(yīng)用在同一個網(wǎng)絡(luò)里。這樣就可以使用諸如浮動IP地址這樣的技術(shù)讓應(yīng)用和一個完全不同的數(shù)據(jù)中心開始通信。你可以配置每個數(shù)據(jù)中心的每臺應(yīng)用服務(wù)器,通過它自己的中間件連接,將流量路由到活躍數(shù)據(jù)中心的機器上。圖12-1描述了這種配置。
如果活躍數(shù)據(jù)中心安裝的MySQL徹底崩潰了,中間件可以路由流量到另外一個數(shù)據(jù)中心的服務(wù)器池中,應(yīng)用無須知道這個變化。
這種配置方法的主要缺點是在一個數(shù)據(jù)中心的Apache服務(wù)器和另外一個數(shù)據(jù)中心的MySQL服務(wù)器之間的延遲比較大。為了緩和這個問題,可以把Web服務(wù)器設(shè)置為重定向模式。這樣通信都會被重定向到放置活躍MySQL服務(wù)器的數(shù)據(jù)中心。還可以使用HTTP代理來實現(xiàn)這一目標(biāo)。
圖12-1顯示了如何使用代理來連接MySQL服務(wù)器,也可以將這個方法和許多別的中間件架構(gòu)結(jié)合在一起,例如LVS和硬件負(fù)載均衡器。
5.4 在應(yīng)用中處理故障轉(zhuǎn)移
有時候讓應(yīng)用來處理故障轉(zhuǎn)移會更簡單或者更加靈潔。例如,如果應(yīng)用遇到一個錯誤,這個錯誤外部觀察者正常情況下是無法察覺的,例如關(guān)于數(shù)據(jù)庫損壞的錯誤日志信息,那么應(yīng)用可以自己來處理故障轉(zhuǎn)移過程。
雖然把故障轉(zhuǎn)移處理過程整合到應(yīng)用中看起來比較吸引人,但可能沒有想象中那么有效。大多數(shù)應(yīng)用有許多組件,例如cron任務(wù)、配置文件,以及用不同語言編寫的腳本。將故障轉(zhuǎn)移整合到應(yīng)用中可能導(dǎo)致應(yīng)用變得太過笨拙,尤其是當(dāng)應(yīng)用增大并變得更加復(fù)雜時。
但是將監(jiān)控構(gòu)建到應(yīng)用中是一個好主意,當(dāng)需要時,能夠立刻開始故障轉(zhuǎn)移過程。應(yīng)用應(yīng)該也能夠管理用戶體驗,例如提供降級功能,并顯示給用戶合適的信息。
6.總結(jié)
可以通過減少宕機來獲得高可用性,這需要從以下兩個方面來思考:增加兩次故障之間的正常運行時間(MTBF),或者減少從故障中恢復(fù)的時間(MTTR)。
要增加兩次故障之間的正常運行時間,就要嘗試去防止故障發(fā)生。悲劇的是,在預(yù)防故障發(fā)生時,它仍然會覺得你做的不夠多,所以預(yù)防故障的努力經(jīng)常會被忽視掉。我們已經(jīng)著重提到了如何在MySQL系統(tǒng)中預(yù)防宕機;具體的細(xì)節(jié)可以參閱我們的白皮書,從上可以獲得。試著從宏機中獲得經(jīng)驗教訓(xùn),但也要謹(jǐn)防在故障根源分析和事后檢驗時集中在某一點上而忽略其他因素。
縮短恢復(fù)時間可能更復(fù)雜并且代價很髙。從簡單和容易的方面來說,可以通過監(jiān)控來更快地發(fā)現(xiàn)問題,并記錄大量的度量值以幫助診斷問題。作為回報,有時候可以在發(fā)生宕機前就發(fā)現(xiàn)問題。監(jiān)控并有選擇地報警以避免無用的信息,但也要及時記錄狀態(tài)和性能度量值。
另外一個減少恢復(fù)時間的策略是為系統(tǒng)建立冗余,并使系統(tǒng)具備故障轉(zhuǎn)移能力,這樣當(dāng)故障發(fā)生時,可以在冗余組件間進(jìn)行切換。不幸的是,冗余會讓系統(tǒng)變得相當(dāng)復(fù)雜。現(xiàn)在應(yīng)用不再是集中化的,而是分布式的,這意味著協(xié)調(diào)、同步、CAP定理、拜占庭將軍問題,以及所有其他各種雜亂的東西。這也是像NDBCluster這樣的系統(tǒng)很難創(chuàng)建并且很難提供足夠的通用性來為所有的工作負(fù)載提供服務(wù)的原因。
本章和前面兩章提及的話題常常被放在一起討論:復(fù)制、可擴展性,以及高可用性。我們已經(jīng)盡量將它們獨立開來,因為這有助于理清這些話題的不同之處。那么這三章有哪些關(guān)聯(lián)之處呢?
在其應(yīng)用增長時,人們一般希望從他們的數(shù)據(jù)庫中知道三件事:
他們希望能夠增加容量來處理新增的負(fù)載而不會損失性能。
他們希望保證不丟失已提交的事務(wù)。
他們希望應(yīng)用能一直在線并處理事務(wù),這樣他們就能夠一直賺錢。
為了達(dá)到這些目的,人們常常首先增加冗余。結(jié)合故障轉(zhuǎn)移機制,通過最小化MTTR來提供高可用性。這些冗余還提供了空閑容量,可以為更多的負(fù)載提供服務(wù)。
當(dāng)然,除了必要的資源外,還必須要有一份數(shù)據(jù)副本。這有助于在損失服務(wù)器時避免丟失數(shù)據(jù),從而增強持久性。生成數(shù)據(jù)副本的唯一辦法是通過某種方法進(jìn)行復(fù)制。不幸的是,數(shù)據(jù)副本可能會引入不一致。處理這個問題需要在節(jié)點間協(xié)調(diào)和通信。這給系統(tǒng)帶來了額外的負(fù)擔(dān);這也是系統(tǒng)或多或少存在擴展性問題的原因。
數(shù)據(jù)副本還需要更多的資源(例如更多的硬盤驅(qū)動器,更多的RAM),這會增加開銷。有一個辦法可以減少資源消耗和維護一致性的開銷,就是為數(shù)據(jù)分區(qū)(分片)并將每個分片分發(fā)到特定的系統(tǒng)中。這可以減少需要復(fù)制的重復(fù)數(shù)據(jù)的次數(shù),并從資源冗余中分離數(shù)據(jù)冗余。
所以,盡管一件事總會導(dǎo)致另外一件事,但我們是在討論一組相關(guān)的觀點和實踐來達(dá)成一系列目的。他們不僅僅是講述同一件事的不同方式。
最后,需要選擇一個對你和應(yīng)用有意義的策略。決定選擇一個完全的端到端(end-to-end)髙可用性策略并不能通過簡單的經(jīng)驗法則來處理,但我們給出的一些粗略的指引也許會有所幫助。
為了獲得很短的宕機時間,需要冗余服務(wù)器能夠及時地接管應(yīng)用的工作負(fù)載。它們必須在線并一直執(zhí)行查詢,而不僅僅是備用,因此它們是“預(yù)熱”過的,處于隨時可用的狀態(tài)。
如果需要很強的可用性保證,就需要諸如MySQLCluster、PerconaXtraDBCluster,或者Clustrix這樣的集群產(chǎn)品。如果能容忍在故障轉(zhuǎn)移過程中稍微慢一些,標(biāo)準(zhǔn)的MySQL復(fù)制也是個很好的選擇。要謹(jǐn)慎使用自動化故障轉(zhuǎn)移機制;如果沒有按照正確的方式工作,它們可能會破壞數(shù)據(jù)。
如果不是很在意故障轉(zhuǎn)移花費的時間,但希望避免數(shù)據(jù)丟失,就需要一些強力保證數(shù)據(jù)
的冗余——例如,同步復(fù)制。在存儲層,這可以通過廉價的DRBD來實現(xiàn),或者使用兩個昂貴的SAN來進(jìn)行同步復(fù)制。也可以選擇在數(shù)據(jù)庫層復(fù)制數(shù)據(jù),可以使用的技術(shù)包括MySQLCluster、PerconaXtraDBCluster或者Clustrix。也可以使用一些中間件,例如TungstenReplicator。如果不需要強有力的保護,并且希望盡量保證簡單,那么正常的異步復(fù)制或半同步復(fù)制在開銷合理時可能是很好的選擇。
或者也可以將應(yīng)用放到云中。為什么不呢?這樣難道不是能夠立刻獲得髙可用性和無限擴展能力嗎?云廠商過多,這里就不做討論。
作者:小家電維修
出處:https://www.cnblogs.com/lizexiong/
轉(zhuǎn)世燕還故榻,為你銜來二月的花。
?
總結(jié)
以上是生活随笔為你收集整理的MySQL的高可用性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于web性能一些特性汇总
- 下一篇: pc端和移动端的区别