25 | 高可用存儲架構(gòu):雙機(jī)架構(gòu)

對任何一個高可用存儲方案,我們需要從以下幾個方面去進(jìn)行思考和分析:

數(shù)據(jù)如何復(fù)制?

各個節(jié)點的職責(zé)是什么?

如何應(yīng)對復(fù)制延遲?

如何應(yīng)對復(fù)制中斷?

常見的高可用存儲架構(gòu)有主備、主從、主主、集群、分區(qū),每一種又可以根據(jù)業(yè)務(wù)的需求進(jìn)行一些特殊的定制化功能,由此衍生出更多的變種。由于不同業(yè)務(wù)的定制功能難以通用化,今天我將針對業(yè)界通用的方案,來分析常見的雙機(jī)高可用架構(gòu):主備、主從、主備 / 主從切換和主主。

一、主備復(fù)制

主備復(fù)制是最常見也是最簡單的一種存儲高可用方案,幾乎所有的存儲系統(tǒng)都提供了主備復(fù)制的功能,例如 MySQL、Redis、MongoDB 等。

1. 基本實現(xiàn)

下面是標(biāo)準(zhǔn)的主備方案結(jié)構(gòu)圖:

其整體架構(gòu)比較簡單,主備架構(gòu)中的“備機(jī)”主要還是起到一個備份作用,并不承擔(dān)實際的業(yè)務(wù)讀寫操作,如果要把備機(jī)改為主機(jī),需要人工操作。

2. 優(yōu)缺點分析

優(yōu)點就是簡單,表現(xiàn)有:

對于客戶端來說,不需要感知備機(jī)的存在,即使災(zāi)難恢復(fù)后,原來的備機(jī)被人工修改為主機(jī)后,對于客戶端來說,只是認(rèn)為主機(jī)的地址換了而已,無須知道是原來的備機(jī)升級為主機(jī)。

對于主機(jī)和備機(jī)來說,雙方只需要進(jìn)行數(shù)據(jù)復(fù)制即可,無須進(jìn)行狀態(tài)判斷和主備切換這類復(fù)雜的操作。

缺點主要有:

備機(jī)僅僅只為備份,并沒有提供讀寫操作,硬件成本上有浪費。

故障后需要人工干預(yù),無法自動恢復(fù)。人工處理的效率是很低的,可能打電話找到能夠操作的人就耗費了 10 分鐘,甚至如果是深更半夜,出了故障都沒人知道。人工在執(zhí)行恢復(fù)操作的過程中也容易出錯,因為這類操作并不常見,可能 1 年就 2、3 次,實際操作的時候很可能遇到各種意想不到的問題。

綜合主備復(fù)制架構(gòu)的優(yōu)缺點,內(nèi)部的后臺管理系統(tǒng)使用主備復(fù)制架構(gòu)的情況會比較多,例如學(xué)生管理系統(tǒng)、員工管理系統(tǒng)、假期管理系統(tǒng)等,因為這類系統(tǒng)的數(shù)據(jù)變更頻率低,即使在某些場景下丟失數(shù)據(jù),也可以通過人工的方式補(bǔ)全。

二、主從復(fù)制

主從復(fù)制和主備復(fù)制只有一字之差,“從”意思是“隨從、仆從”,“備”的意思是備份。我們可以理解為仆從是要幫主人干活的,這里的干活就是承擔(dān)“讀”的操作。也就是說,主機(jī)負(fù)責(zé)讀寫操作,從機(jī)只負(fù)責(zé)讀操作,不負(fù)責(zé)寫操作。

1. 基本實現(xiàn)

下面是標(biāo)準(zhǔn)的主從復(fù)制架構(gòu):

與主備復(fù)制架構(gòu)比較類似,主要的差別點在于從機(jī)正常情況下也是要提供讀的操作。

2. 優(yōu)缺點分析

主從復(fù)制與主備復(fù)制相比,優(yōu)點有:

主從復(fù)制在主機(jī)故障時,讀操作相關(guān)的業(yè)務(wù)可以繼續(xù)運行。

主從復(fù)制架構(gòu)的從機(jī)提供讀操作,發(fā)揮了硬件的性能。

缺點有:

主從復(fù)制架構(gòu)中,客戶端需要感知主從關(guān)系,并將不同的操作發(fā)給不同的機(jī)器進(jìn)行處理,復(fù)雜度比主備復(fù)制要高。

主從復(fù)制架構(gòu)中,從機(jī)提供讀業(yè)務(wù),如果主從復(fù)制延遲比較大,業(yè)務(wù)會因為數(shù)據(jù)不一致出現(xiàn)問題。

故障時需要人工干預(yù)。

綜合主從復(fù)制的優(yōu)缺點,一般情況下,寫少讀多的業(yè)務(wù)使用主從復(fù)制的存儲架構(gòu)比較多。例如,論壇、BBS、新聞網(wǎng)站這類業(yè)務(wù),此類業(yè)務(wù)的讀操作數(shù)量是寫操作數(shù)量的 10 倍甚至 100 倍以上。

三、雙機(jī)切換

1. 設(shè)計關(guān)鍵

主備復(fù)制和主從復(fù)制方案存在兩個共性的問題:

主機(jī)故障后,無法進(jìn)行寫操作。

如果主機(jī)無法恢復(fù),需要人工指定新的主機(jī)角色。

雙機(jī)切換就是為了解決這兩個問題而產(chǎn)生的,包括主備切換和主從切換兩種方案。簡單來說,這兩個方案就是在原有方案的基礎(chǔ)上增加“切換”功能,即系統(tǒng)自動決定主機(jī)角色,并完成角色切換。由于主備切換和主從切換在切換的設(shè)計上沒有差別,我接下來以主備切換為例,一起來看看雙機(jī)切換架構(gòu)是如何實現(xiàn)的。

要實現(xiàn)一個完善的切換方案,必須考慮這幾個關(guān)鍵的設(shè)計點:

主備間狀態(tài)判斷

主要包括兩方面:狀態(tài)傳遞的渠道,以及狀態(tài)檢測的內(nèi)容。

狀態(tài)傳遞的渠道:是相互間互相連接,還是第三方仲裁?

狀態(tài)檢測的內(nèi)容:例如機(jī)器是否掉電、進(jìn)程是否存在、響應(yīng)是否緩慢等。

切換決策

主要包括幾方面:切換時機(jī)、切換策略、自動程度。

切換時機(jī):什么情況下備機(jī)應(yīng)該升級為主機(jī)?是機(jī)器掉電后備機(jī)才升級,還是主機(jī)上的進(jìn)程不存在就升級,還是主機(jī)響應(yīng)時間超過 2 秒就升級,還是 3 分鐘內(nèi)主機(jī)連續(xù)重啟 3 次就升級等。

切換策略:原來的主機(jī)故障恢復(fù)后,要再次切換,確保原來的主機(jī)繼續(xù)做主機(jī),還是原來的主機(jī)故障恢復(fù)后自動成為新的備機(jī)?

自動程度:切換是完全自動的,還是半自動的?例如,系統(tǒng)判斷當(dāng)前需要切換,但需要人工做最終的確認(rèn)操作(例如,單擊一下“切換”按鈕)。

數(shù)據(jù)沖突解決

當(dāng)原有故障的主機(jī)恢復(fù)后,新舊主機(jī)之間可能存在數(shù)據(jù)沖突。例如,用戶在舊主機(jī)上新增了一條 ID 為 100 的數(shù)據(jù),這個數(shù)據(jù)還沒有復(fù)制到舊的備機(jī),此時發(fā)生了切換,舊的備機(jī)升級為新的主機(jī),用戶又在新的主機(jī)上新增了一條 ID 為 100 的數(shù)據(jù),當(dāng)舊的故障主機(jī)恢復(fù)后,這兩條 ID 都為 100 的數(shù)據(jù),應(yīng)該怎么處理?

以上設(shè)計點并沒有放之四海而皆準(zhǔn)的答案,不同的業(yè)務(wù)要求不一樣,所以切換方案比復(fù)制方案不只是多了一個切換功能那么簡單,而是復(fù)雜度上升了一個量級。形象點來說,如果復(fù)制方案的代碼是 1000 行,那么切換方案的代碼可能就是 10000 行,多出來的那 9000 行就是用于實現(xiàn)上面我所講的 3 個設(shè)計點的。

2. 常見架構(gòu)

根據(jù)狀態(tài)傳遞渠道的不同,常見的主備切換架構(gòu)有三種形式:互連式、中介式和模擬式。

(1)互連式

故名思議,互連式就是指主備機(jī)直接建立狀態(tài)傳遞的渠道,架構(gòu)圖請注意與主備復(fù)制架構(gòu)對比。

你可以看到,在主備復(fù)制的架構(gòu)基礎(chǔ)上,主機(jī)和備機(jī)多了一個“狀態(tài)傳遞”的通道,這個通道就是用來傳遞狀態(tài)信息的。這個通道的具體實現(xiàn)可以有很多方式:

可以是網(wǎng)絡(luò)連接(例如,各開一個端口),也可以是非網(wǎng)絡(luò)連接(用串口線連接)。

可以是主機(jī)發(fā)送狀態(tài)給備機(jī),也可以是備機(jī)到主機(jī)來獲取狀態(tài)信息。

可以和數(shù)據(jù)復(fù)制通道共用,也可以獨立一條通道。

狀態(tài)傳遞通道可以是一條,也可以是多條,還可以是不同類型的通道混合(例如,網(wǎng)絡(luò) + 串口)。

為了充分利用切換方案能夠自動決定主機(jī)這個優(yōu)勢,客戶端這里也會有一些相應(yīng)的改變,常見的方式有:

為了切換后不影響客戶端的訪問,主機(jī)和備機(jī)之間共享一個對客戶端來說唯一的地址。例如虛擬 IP,主機(jī)需要綁定這個虛擬的 IP。

客戶端同時記錄主備機(jī)的地址,哪個能訪問就訪問哪個;備機(jī)雖然能收到客戶端的操作請求,但是會直接拒絕,拒絕的原因就是“備機(jī)不對外提供服務(wù)”。

缺點在于:

如果狀態(tài)傳遞的通道本身有故障(例如,網(wǎng)線被人不小心踢掉了),那么備機(jī)也會認(rèn)為主機(jī)故障了從而將自己升級為主機(jī),而此時主機(jī)并沒有故障,最終就可能出現(xiàn)兩個主機(jī)。

雖然可以通過增加多個通道來增強(qiáng)狀態(tài)傳遞的可靠性,但這樣做只是降低了通道故障概率而已,不能從根本上解決這個缺點,而且通道越多,后續(xù)的狀態(tài)決策會更加復(fù)雜,因為對備機(jī)來說,可能從不同的通道收到了不同甚至矛盾的狀態(tài)信息。

(2)中介式

中介式指的是在主備兩者之外引入第三方中介,主備機(jī)之間不直接連接,而都去連接中介,并且通過中介來傳遞狀態(tài)信息,其架構(gòu)圖如下:

對比一下互連式切換架構(gòu),我們可以看到,主機(jī)和備機(jī)不再通過互聯(lián)通道傳遞狀態(tài)信息,而是都將狀態(tài)上報給中介這一角色。單純從架構(gòu)上看,中介式似乎比互連式更加復(fù)雜了,首先要引入中介,然后要各自上報狀態(tài)。然而事實上,中介式架構(gòu)在狀態(tài)傳遞和決策上卻更加簡單了,這是為何呢?

連接管理更簡單:主備機(jī)無須再建立和管理多種類型的狀態(tài)傳遞連接通道,只要連接到中介即可,實際上是降低了主備機(jī)的連接管理復(fù)雜度。

例如,互連式要求主機(jī)開一個監(jiān)聽端口,備機(jī)來獲取狀態(tài)信息;或者要求備機(jī)開一個監(jiān)聽端口,主機(jī)推送狀態(tài)信息到備機(jī);如果還采用了串口連接,則需要增加串口連接管理和數(shù)據(jù)讀取。采用中介式后,主備機(jī)都只需要把狀態(tài)信息發(fā)送給中介,或者從中介獲取對方的狀態(tài)信息。無論是發(fā)送還是獲取,主備機(jī)都是作為中介的客戶端去操作,復(fù)雜度會降低。

狀態(tài)決策更簡單:主備機(jī)的狀態(tài)決策簡單了,無須考慮多種類型的連接通道獲取的狀態(tài)信息如何決策的問題,只需要按照下面簡單的算法即可完成狀態(tài)決策。

無論是主機(jī)還是備機(jī),初始狀態(tài)都是備機(jī),并且只要與中介斷開連接,就將自己降級為備機(jī),因此可能出現(xiàn)雙備機(jī)的情況。

主機(jī)與中介斷連后,中介能夠立刻告知備機(jī),備機(jī)將自己升級為主機(jī)。

如果是網(wǎng)絡(luò)中斷導(dǎo)致主機(jī)與中介斷連,主機(jī)自己會降級為備機(jī),網(wǎng)絡(luò)恢復(fù)后,舊的主機(jī)以新的備機(jī)身份向中介上報自己的狀態(tài)。

如果是掉電重啟或者進(jìn)程重啟,舊的主機(jī)初始狀態(tài)為備機(jī),與中介恢復(fù)連接后,發(fā)現(xiàn)已經(jīng)有主機(jī)了,保持自己備機(jī)狀態(tài)不變。

主備機(jī)與中介連接都正常的情況下,按照實際的狀態(tài)決定是否進(jìn)行切換。例如,主機(jī)響應(yīng)時間超過 3 秒就進(jìn)行切換,主機(jī)降級為備機(jī),備機(jī)升級為主機(jī)即可。

雖然中介式架構(gòu)在狀態(tài)傳遞和狀態(tài)決策上更加簡單,但并不意味著這種優(yōu)點是沒有代價的,其關(guān)鍵代價就在于如何實現(xiàn)中介本身的高可用。如果中介自己宕機(jī)了,整個系統(tǒng)就進(jìn)入了雙備的狀態(tài),寫操作相關(guān)的業(yè)務(wù)就不可用了。這就陷入了一個遞歸的陷阱:為了實現(xiàn)高可用,我們引入中介,但中介本身又要求高可用,于是又要設(shè)計中介的高可用方案……如此遞歸下去就無窮無盡了。

MongoDB 的 Replica Set 采取的就是這種方式,其基本架構(gòu)如下:

http://img.my.csdn.net/uploads/201301/13/1358056331_2790.png

MongoDB(M) 表示主節(jié)點,MongoDB(S) 表示備節(jié)點,MongoDB(A) 表示仲裁節(jié)點。主備節(jié)點存儲數(shù)據(jù),仲裁節(jié)點不存儲數(shù)據(jù)??蛻舳送瑫r連接主節(jié)點與備節(jié)點,不連接仲裁節(jié)點。

幸運的是,開源方案已經(jīng)有比較成熟的中介式解決方案,例如 ZooKeeper 和 Keepalived。ZooKeeper 本身已經(jīng)實現(xiàn)了高可用集群架構(gòu),因此已經(jīng)幫我們解決了中介本身的可靠性問題,在工程實踐中推薦基于 ZooKeeper 搭建中介式切換架構(gòu)。

(3)模擬式

模擬式指主備機(jī)之間并不傳遞任何狀態(tài)數(shù)據(jù),而是備機(jī)模擬成一個客戶端,向主機(jī)發(fā)起模擬的讀寫操作,根據(jù)讀寫操作的響應(yīng)情況來判斷主機(jī)的狀態(tài)。其基本架構(gòu)如下:

對比一下互連式切換架構(gòu),我們可以看到,主備機(jī)之間只有數(shù)據(jù)復(fù)制通道,而沒有狀態(tài)傳遞通道,備機(jī)通過模擬的讀寫操作來探測主機(jī)的狀態(tài),然后根據(jù)讀寫操作的響應(yīng)情況來進(jìn)行狀態(tài)決策。

模擬式切換與互連式切換相比,優(yōu)點是實現(xiàn)更加簡單,因為省去了狀態(tài)傳遞通道的建立和管理工作。

簡單既是優(yōu)點,同時也是缺點。因為模擬式讀寫操作獲取的狀態(tài)信息只有響應(yīng)信息(例如,HTTP 404,超時、響應(yīng)時間超過 3 秒等),沒有互連式那樣多樣(除了響應(yīng)信息,還可以包含 CPU 負(fù)載、I/O 負(fù)載、吞吐量、響應(yīng)時間等),基于有限的狀態(tài)來做狀態(tài)決策,可能出現(xiàn)偏差。

四、主主復(fù)制

主主復(fù)制指的是兩臺機(jī)器都是主機(jī),互相將數(shù)據(jù)復(fù)制給對方,客戶端可以任意挑選其中一臺機(jī)器進(jìn)行讀寫操作,下面是基本架構(gòu)圖。

兩臺都是主機(jī),不存在切換的概念。

客戶端無須區(qū)分不同角色的主機(jī),隨便將讀寫操作發(fā)送給哪臺主機(jī)都可以。

從上面的描述來看,主主復(fù)制架構(gòu)從總體上來看要簡單很多,無須狀態(tài)信息傳遞,也無須狀態(tài)決策狀態(tài)切換。復(fù)雜性:數(shù)據(jù)能夠雙向復(fù)制,而很多數(shù)據(jù)是不能雙向復(fù)制的。例如:

用戶注冊后生成的用戶 ID,如果按照數(shù)字增長,那就不能雙向復(fù)制,否則就會出現(xiàn) X 用戶在主機(jī) A 注冊,分配的用戶 ID 是 100,同時 Y 用戶在主機(jī) B 注冊,分配的用戶 ID 也是 100,這就出現(xiàn)了沖突。

庫存不能雙向復(fù)制。例如,一件商品庫存 100 件,主機(jī) A 上減了 1 件變成 99,主機(jī) B 上減了 2 件變成 98,然后主機(jī) A 將庫存 99 復(fù)制到主機(jī) B,主機(jī) B 原有的庫存 98 被覆蓋,變成了 99,而實際上此時真正的庫存是 97。類似的還有余額數(shù)據(jù)。

因此,主主復(fù)制架構(gòu)對數(shù)據(jù)的設(shè)計有嚴(yán)格的要求,一般適合于那些臨時性、可丟失、可覆蓋的數(shù)據(jù)場景。例如,用戶登錄產(chǎn)生的 session 數(shù)據(jù)(可以重新登錄生成)、用戶行為的日志數(shù)據(jù)(可以丟失)、論壇的草稿數(shù)據(jù)(可以丟失)等。

小結(jié)

政府信息公開網(wǎng)站的信息存儲系統(tǒng),你會采取哪種架構(gòu)?談?wù)勀愕姆治龊屠碛伞?/p>

評論:

政府信息網(wǎng)站使用主備或者主從架構(gòu)就可以了。信息都是人工錄入,可以補(bǔ)錄。數(shù)據(jù)本來對實時性要求不高,所以出了故障人工修復(fù)也來得及。所以主備就夠了,如果為了照顧形象可以用主從,保證主機(jī)故障后仍然可以查,不能新發(fā)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容