【作者】趙海
前文鏈接:企業(yè)容災(zāi)架構(gòu)選型解析(一):必知概念、跨中心數(shù)據(jù)復(fù)制技術(shù)
企業(yè)容災(zāi)架構(gòu)選型解析(二):數(shù)據(jù)容錯恢復(fù)技術(shù)、關(guān)鍵故障切換
腦裂(split-brain)就是“大腦分裂”,也就是本來一個“大腦”,由于某些原因被拆分了兩個或多個“大腦”,我們都知道,如果一個人有多個大腦,并且相互獨立的話,那么必然會出問題。
在容災(zāi)架構(gòu)設(shè)計當中,我們經(jīng)常會利用一些 HA、Cluster等高可用架構(gòu)在其中,而且一般都是借助于跨地域L2網(wǎng)絡(luò),采用跨數(shù)據(jù)中心的方式在某一個功能層組成一個獨立的集群,例如數(shù)據(jù)庫集群、存儲網(wǎng)關(guān)集群等 。假設(shè)因為兩個數(shù)據(jù)中心節(jié)點通訊中斷故障導(dǎo)致形成了兩個獨立的集群,彼此獨立工作,那么這就是腦裂。正如下圖所示情況。
第一個問題:為什么會集群可能產(chǎn)生腦裂?
這個問題需要回到集群的仲裁機制上來,一般來講集群的仲裁算法是以每一個節(jié)點可以獲得仲裁資源的多少來判斷誰是集群的主導(dǎo)。集群的仲裁資源無非是來自網(wǎng)絡(luò)層面的心跳信息和共享存儲的磁盤心跳資源,在普通的節(jié)點層故障場合下,發(fā)生故障的節(jié)點可以獲得的仲裁資源就會少于其他節(jié)點,那么就不會發(fā)生腦裂問題。但是在一種特殊的場合(雙數(shù)據(jù)中心之間的網(wǎng)絡(luò)發(fā)生了故障),兩個節(jié)點可以獲得的仲裁資源是一樣的,網(wǎng)絡(luò)彼此不能互通,存儲彼此不能看到對方,這樣的的場景下仲裁就會失效,腦裂發(fā)生。
第二個問題:集群如果發(fā)生了腦裂問題,那么會造成什么樣的結(jié)果?
那么為什么說對于容災(zāi)架構(gòu)來講,腦裂是災(zāi)難性的事件呢?如果從一個統(tǒng)一集群的調(diào)度變成兩個相互獨立的集群調(diào)度,意味著雙方的寫操作相互也是獨立的,但是他們的存儲空間是共享的, AA模式下通過鎖機制控制并發(fā),HA模式下通過存儲卷的Owner控制寫的權(quán)限。但是獨立之后意味著兩個集群可以隨時寫入同樣的存儲地址,必然會造成臟寫臟讀等一系列數(shù)據(jù)不一致事件。這對業(yè)務(wù)來講是災(zāi)難性的。
如圖所示,以兩個節(jié)點的 Oracle RAC為例來講,ORACLE RAC ASM管理模式下,磁盤組通常有三個( DATA, FRA, OCR),在OCR磁盤組當中所有的磁盤中存儲的數(shù)據(jù)包括兩部分,一部分是Vote File,另外一部分就是OCR(Oracle Cluster Registry)。Vote File是用來記錄集群節(jié)點的磁盤心跳信息,而OCR是保存集群配置信息的數(shù)據(jù)。Vote File,以整個文件的方式存儲在OCR磁盤上,不做任何條帶。下圖是其信息記錄的一個說明:
Instance1 | OK | NG | NG |
Instance2 | NG | OK | OK |
Instance3 | NG | OK | OK |
Instance1 | Instance2 | Instance3 |
以上是一個三節(jié)點的ORACLE RAC集群的Vote FIle的一個示意矩陣,每一行是一個節(jié)點的寫入的信息,例如第一行,Instance1分別把其對集群中的三個成員(1、2、3)進行私網(wǎng)檢測的結(jié)果寫入到仲裁文件當中,Instance2、Instance3同樣把其檢測結(jié)果寫入仲裁文件,最終組成了三個節(jié)點的仲裁矩陣。當私網(wǎng)發(fā)生故障而從網(wǎng)絡(luò)上導(dǎo)致集群分割為幾個孤島子集的時候,網(wǎng)絡(luò)心跳同票數(shù)情況下,仲裁算法有兩個非常重要的規(guī)則:
① 保障隔離后的集群子集中節(jié)點數(shù)目最多的子集存活。
② 當隔離后的集群子集獲得的仲裁票數(shù)相等時,保障實例號小者存活。
當兩個節(jié)點的Oracle RAC集群面臨私網(wǎng)故障的時候,必然會遵循以上規(guī)則,從規(guī)則內(nèi)容上可以看出,第一條規(guī)則基本沒有什么意義,雙方的資源是對等的;但是第二條規(guī)則直接決定了集群的最終狀態(tài),那就是實例號小的節(jié)點成為新的集群,這就避免了腦裂的存在。
所謂資源失衡配置解決方案,就是要在容災(zāi)設(shè)計之初就保障主數(shù)據(jù)中心的資源配置要多于災(zāi)備中心,使得兩個數(shù)據(jù)中心節(jié)點可以獲取到的仲裁資源處于不平衡狀態(tài)。
如上兩圖所示,容災(zāi)設(shè)計的時候可以將主備數(shù)據(jù)中心的節(jié)點分布數(shù)量或者仲裁文件分布數(shù)量按照2:1的非平衡策略設(shè)置。那么按照集群仲裁的一般規(guī)則:發(fā)生集群分裂故障的時候,可以獲得更多仲裁資源的子集將成為新的集群。當發(fā)生數(shù)據(jù)中心之間的網(wǎng)絡(luò)故障的時候:
第一種架構(gòu),主數(shù)據(jù)中心內(nèi)部兩個節(jié)點可以獲取到更多的網(wǎng)絡(luò)心跳,自然會接管集群。
第二種架構(gòu),主數(shù)據(jù)中心的節(jié)點可以獲取到更多的磁盤心跳,同樣會接管集群。
這也符合我們設(shè)計之初衷。但是,這種方法只適合于AA模式的多節(jié)點集群,不適合HA模式的架構(gòu)。
自定義優(yōu)先級的解決方案,其實本質(zhì)上與Oracle RAC的仲裁算法第二條“當隔離后的集群子集獲得的仲裁票數(shù)相等時,保障實例號小者存活?!笔且粯拥?。只不過對于Oracle RAC,當通過第一條規(guī)則無法判斷的時候(節(jié)點獲取的仲裁資源矩陣是平衡的),它默認采用了實例號定義其優(yōu)先級。
而其他的一些容災(zāi)方案,這個優(yōu)先級定義的靈活性留給了客戶。例如圖當中的VPLEX產(chǎn)品,尤其是在雙活架構(gòu)的設(shè)計當中,有可能因為地域、設(shè)備新舊、運營管理等方面的差異,往往災(zāi)備中心的運行能力會稍差,那么發(fā)生數(shù)據(jù)中心之間隔離的這種故障時,大家往往希望保留主數(shù)據(jù)中心的運行。那么這個時候客戶就可以根據(jù)主數(shù)據(jù)中心的節(jié)點標識來固定其仲裁優(yōu)先級。
網(wǎng)絡(luò)資源是集群仲裁當中非常重要的一種心跳資源,因此通過第三方網(wǎng)絡(luò)資源的可達性心跳信息來判斷對稱集群分裂后的新秩序也是一種非常有效的方法。一般在以存儲網(wǎng)關(guān)實現(xiàn)數(shù)據(jù)雙寫的容災(zāi)架構(gòu)當中比較常見,比如 VPLEX、SVC、MCC等。具體原理如下圖所示:
第三方仲裁點需要滿足的條件:
① 與主備兩個數(shù)據(jù)中心 L3可達,并且網(wǎng)絡(luò)質(zhì)量穩(wěn)定。
② 仲裁點一般需要安裝具備網(wǎng)絡(luò)探測功能的虛擬服務(wù)器或者物理服務(wù)器,具備運行條件。
如圖所示,仲裁點服務(wù)器上的軟件會與組成集群的存儲器網(wǎng)關(guān)兩個節(jié)點分別發(fā)送PING/ACK來確認雙方的健康情況,集群會把兩個節(jié)點與第三方仲裁點的網(wǎng)絡(luò)仲裁心跳看做是最終的裁判。Vplex Witness 通過管理 IP 網(wǎng)絡(luò)連接至兩個集群節(jié)點,通過將其自身的觀察與集群定期報告的信息進行協(xié)調(diào),讓集群可區(qū)分是集群內(nèi)故障還是集群間鏈路故障,并在這些情況下自動繼續(xù)相應(yīng)站點上的 I/O 服務(wù)。Vplex Witness 僅當分離規(guī)則沒有定義時才會生效。當然細心的讀者可能產(chǎn)生了一個新的問題:
如果數(shù)據(jù)中心與第三仲裁站點的網(wǎng)絡(luò)發(fā)生故障,那會不會影響集群本身的運行?****
什么是仲裁?仲裁是只有發(fā)生集群隔離故障的時候才會起作用,如果沒有發(fā)生數(shù)據(jù)中心之間的隔離故障的時候,即使他們的一方或者雙方于第三煩仲裁站點發(fā)生網(wǎng)絡(luò)暫時中斷的事件,也不會對既有集群造成任何健康影響。我們需要做的是保障第三方仲裁資源在發(fā)生故障的時候有效就可以了(監(jiān)控&及時修復(fù))。
存儲一般是數(shù)據(jù)庫集群當中非常關(guān)鍵的仲裁資源,數(shù)據(jù)庫集群的節(jié)點負載比較重,不像存儲網(wǎng)關(guān)模式的集群,可以再設(shè)計與 Witness Node的通訊接口。所以在這類技術(shù)方案的容災(zāi)設(shè)計當中,通常會用第三方存儲陣列來作為集群的第三方仲裁點。例如Oracle Extended RAC、HA&Oracle、HA&DB2等。具體原理如下圖所示:
a. 第三方站點放置一個存儲陣列、并且與兩個數(shù)據(jù)中心網(wǎng)絡(luò)穩(wěn)定可達。
b. 存儲陣列以NFS或者ISCSI方式提供共享存儲卷或文件服務(wù)給兩個中心的集群節(jié)點。
c. 集群配置的時候,將這個共享存儲卷或者文件作為集群的磁盤仲裁之一。
當雙中心的集群發(fā)生隔離故障的時候,集群通過第三方的仲裁磁盤或者文件來判斷集群的新秩序。
集群發(fā)生的故障場景有很多,有可能是網(wǎng)卡故障導(dǎo)致節(jié)點隔離,也有可能是鏈路問題導(dǎo)致節(jié)點隔離。鏈路問題本身又分很多種,有一種場景及時存在第三仲裁的場景下,依然有可能是對稱平衡的狀態(tài)。如下圖所示:
如圖所示,當兩個中心之間的鏈路中斷,但是其他各條線路都完好無損的情況下,及時存在第三方仲裁,那么集群分裂后的仲裁資源分布依然是平衡對稱的,這又該如何解決呢?
我們認為有兩種解決方式:
1、優(yōu)先級定義解決方案,也就是說我們在第二節(jié)提到的解決方案必須成為容災(zāi)設(shè)計的必選項。
2、仲裁爭奪方案,無論是三方的網(wǎng)絡(luò)仲裁還是存儲仲裁,假設(shè)出現(xiàn)集群隔離故障后各個節(jié)點開始爭奪這個資源,那么必然有先后順序之分,先到先得的規(guī)則來重新定義集群新秩序。這種方案尤其適用于以HA模式的容災(zāi)架構(gòu)。當然具體如何爭奪,如何確認爭奪維度及結(jié)果就需要根據(jù)不同產(chǎn)品架構(gòu)來探討了。
我們知道在容災(zāi)整體設(shè)計當中,需要有網(wǎng)絡(luò)層、計算層、數(shù)據(jù)庫服務(wù)層、存儲服務(wù)層等各方面的設(shè)計。
他們在縱向上是疊加的形態(tài)。如圖所示:
上圖是我們將容災(zāi)設(shè)計當中縱向抽象出來的幾個功能層,其中數(shù)據(jù)跨中心復(fù)制是實現(xiàn)雙活容災(zāi)的前提條件,它是支撐網(wǎng)絡(luò)及計算層具備容災(zāi)意義的基礎(chǔ),那么如何實現(xiàn)數(shù)據(jù)復(fù)制,我們在《企業(yè)容災(zāi)選型指南- 2:數(shù)據(jù)復(fù)制技術(shù)》當中介紹了很多方法,基本上集中在數(shù)據(jù)庫層和存儲層去實現(xiàn)。假設(shè)我們采用了存儲層的數(shù)據(jù)復(fù)制技術(shù),存儲層提供的虛擬分布式卷對于數(shù)據(jù)庫集群來講是透明的。
當數(shù)據(jù)中心之間發(fā)生線路故障的時候,數(shù)據(jù)庫集群和存儲網(wǎng)關(guān)組成的集群是兩個不同的集群,他們的仲裁結(jié)果會不會不一致?
集群的仲裁是瞬間完成的,集群的仲裁觸發(fā)條件有可能有片刻的先后順序之差,數(shù)據(jù)庫層的仲裁先于存儲層的仲裁,那么雖然概率小,但是這個沖突是完全有可能的。但是如果存儲的仲裁發(fā)生在數(shù)據(jù)庫之前,理論上這個沖突是可以避免的,因為存儲卷是數(shù)據(jù)庫集群健康運行的前提。
以 Oracle RAC 和VPLEX結(jié)合的架構(gòu)為例,我們探討它的解決方法。
風(fēng)險發(fā)生的引發(fā)點有兩個:
① 集群的仲裁觸發(fā) 條件導(dǎo)致的仲裁順序發(fā)生紊亂;
② 對稱平衡狀態(tài)下的仲裁規(guī)則沖突。
資源被1:1割裂之后的默認仲裁策略不一致。也就是說,只要控制這兩個引發(fā)點,那么這個問題從理論上也就避免了。對于第一個引發(fā)點來講,實際上存儲集群的默認仲裁觸發(fā)時間會是15秒左右,而數(shù)據(jù)庫仲裁觸發(fā)的控制參數(shù)由misscount這個參數(shù)來決定,所以只要我們將misscount這個參數(shù)調(diào)整到 1 5秒之后,也就是說理論上絕對保障存儲集群仲裁在前,而數(shù)據(jù)庫仲裁在后,那么第 1 個引發(fā)點就沒有了。對于第二個引發(fā)點來講,假設(shè)兩站點節(jié)點資源對等,仲裁選票同樣對等的情況下,存儲集群會有一個默認的Winner策略,同樣在這種情況下數(shù)據(jù)庫集群也有一個默認仲裁策略:選擇實例號小的集群存活。只要我們保證這兩個策略結(jié)果的一致性,那么第 2 個引發(fā)點也就不存在了。
原題:企業(yè)容災(zāi)選型指南-5:腦裂問題探討