(2022.06.27 Mon)
存儲高可用的方案本質(zhì)都是將數(shù)據(jù)復制到多個存儲設備,通過數(shù)據(jù)冗余實現(xiàn)高可用稠歉。其復雜性體現(xiàn)在如何應對復制延遲和中斷導致的數(shù)據(jù)不一致問題射众。高可用存儲方案澎胡,需要注意如下問題:
- 數(shù)據(jù)如何復制
- 各個節(jié)點的職責
- 如何應對復制延遲
- 如何應對復制中斷
常用的高可用存儲架構有主備、主從预厌、主主阿迈、集群、分區(qū)轧叽。下面分別介紹苗沧。
主備模式primary-replica
主備模式是最常見的存儲高可用方案,幾乎所有存儲系統(tǒng)都提供了主備復制的功能炭晒,MySQL待逞、Redis、MongoDB网严。
主備框圖如下
主備方案的設計如下:
- 主機存儲數(shù)據(jù)识樱,通過復制通道將數(shù)據(jù)復制到備機
- 正常情況下,client無論讀寫操作震束,都發(fā)送給主機怜庸,備機不提供服務
- 主機故障,客戶端不會自動將請求發(fā)給備機垢村,整個系統(tǒng)處于不可用狀態(tài)割疾,不能讀寫,但數(shù)據(jù)沒有丟失
- 若主機恢復嘉栓,不管人工還是自動宏榕,client繼續(xù)訪問主機,主機繼續(xù)將數(shù)據(jù)發(fā)給備機
- 若主機不恢復侵佃,則需要人工操作麻昼,將備機升級為主機,然后讓客戶端訪問新主機趣钱,原來的備機升級為主機涌献,同時為了保證主備架構胚宦,人工增加新的機器作為備機
- 若主機不可恢復首有,成功寫入主機但沒有復制到備機的數(shù)據(jù)丟失燕垃,需要人工排查和恢復,同時需要應對數(shù)據(jù)永久丟失的風險
- 主備間數(shù)據(jù)有延遲井联,由于備機不對外提供讀寫服務卜壕,因此對業(yè)務無影響。如果延遲多烙常,且主機故障轴捎,則可能丟失較多數(shù)據(jù)。一般做法是做復制延遲的監(jiān)控措施蚕脏,當延遲的數(shù)據(jù)量較大時及時報警侦副,由人工干預處理。
簡單來說驼鞭,備機只起到備份的作用秦驯,不承擔業(yè)務讀寫。
主備復制的優(yōu)缺點
優(yōu)點是簡單
- 客戶端不需要感知備機的存在挣棕,也無需知道主備機的身份在災難恢復后發(fā)生轉(zhuǎn)變
- 主備雙方只需要金牛星數(shù)據(jù)復制译隘,無需進行狀態(tài)判斷和主備倒換這類復雜的操作
缺點
- 備機僅僅只為備份,并沒有提供讀寫操作洛心,硬件成本有浪費
- 故障后需要人工干預固耘,無法自動恢復。
內(nèi)部的后臺管理系統(tǒng)使用主備復制架構比較多词身,比如學生管理系統(tǒng)厅目、員工管理系統(tǒng)、假期管理系統(tǒng)等偿枕。數(shù)據(jù)變更頻率低璧瞬,即使丟失也可以通過人工的方式補全。
(2022.06.28 Tues)
主從復制master-slave/primary-secondary
不同于主備復制渐夸,這里的"從"可理解為幫"主"機器承擔任務嗤锉,也就是"讀"的操作。具體來說就是主機負責讀寫操作墓塌,從機只負責讀操作瘟忱。
框架如圖
細節(jié)如下:
- 主機存儲數(shù)據(jù),通過復制通道復制到從機
- 客戶端寫操作發(fā)給主機苫幢,讀操作發(fā)給主機和從機访诱,具體的讀取對象根據(jù)業(yè)務特點選擇
- 主機故障的情況下寫操作不可用,但讀操作依然可使用韩肝,如論壇的寫操作(發(fā)帖)不可用触菜,但是讀操作(看帖)可以用
- 主機故障恢復,客戶端繼續(xù)發(fā)寫申請給主機
- 如果主機不能恢復哀峻,需要人工將備機升級為主機涡相,執(zhí)行讀寫操作哲泊;為保持主從架構,增加新的機器作為從機
- 主機不能恢復催蝗,成功寫入主機但沒有復制到從機的數(shù)據(jù)面臨丟失風險切威,要人工排查,需要考慮這些數(shù)據(jù)如果永遠丟失的風險
- 如果數(shù)據(jù)延遲大丙号,會導致剛寫入的數(shù)據(jù)無法在從機讀出的情況
- 如果延遲多先朦,恰好主機損壞,會導致數(shù)據(jù)丟失犬缨,故復制延遲需要注意喳魏。可對復制延遲做監(jiān)控怀薛,延遲較大需要報警和人工干預截酷。
對比主備操作的優(yōu)缺點:
- 主機故障,讀操作不受影響
- 從機提供讀操作乾戏,發(fā)揮了硬件性能
- 主從比主備復雜迂苛,體現(xiàn)在客戶需要感知主從關系,將不同的操作發(fā)給不同主機
綜上鼓择,業(yè)務中讀多寫少的業(yè)務使用主從復制的架構比較多三幻。論壇、新聞等讀業(yè)務遠大于寫業(yè)務的需求呐能。
主備倒換和主從倒換
設計關鍵:
- 主備間狀態(tài)轉(zhuǎn)換
- 狀態(tài)轉(zhuǎn)換渠道:是否互聯(lián)互通還是通過第三方
- 檢測內(nèi)容:機器掉電念搬、進程存在、響應時長等
- 倒換決策
- 倒換條件:主備/從機轉(zhuǎn)換的條件判斷摆出,是下面若干條件之一朗徊,機器掉電、主機上進程不存在偎漫、主機響應時間過久比如3秒爷恳、短時間內(nèi)多次重啟,或者其他條件
- 倒換后策略:考慮a)備機升級為主機且主機修復后象踊,是否需要再次轉(zhuǎn)換温亲,或者b)主機修復后自動成為新的備機
- 自動程度:自動、半自動杯矩、人工
- 數(shù)據(jù)沖突
故障之后可能存在數(shù)據(jù)沖突栈虚,如舊主機新增數(shù)據(jù)可能還沒有復制到舊的備機,發(fā)生轉(zhuǎn)換史隆,舊備機成為主機魂务,但沒有新加入舊主機的數(shù)據(jù)
解決方案
三種方案的區(qū)別在于狀態(tài)傳遞渠道不同,分別是互連式、中介式粘姜、模擬式蚣驼。
互連式
主備機直接建立狀態(tài)傳遞的渠道
主備之間除了數(shù)據(jù)復制通道,多了一條狀態(tài)轉(zhuǎn)譯通道相艇,實現(xiàn)方式如下:
- 網(wǎng)絡連接,比如開新端口纯陨,或者非網(wǎng)絡連接坛芽,如串口線連接
- 主機發(fā)送狀態(tài)給備機,或備機到主機來獲取狀態(tài)信息
- 與數(shù)據(jù)復制共享一條通道翼抠,或獨立一條通道
- 狀態(tài)傳輸通道可一條可多條咙轩,可以是不同類型通道的混合,比如端口加串口
客戶端也需要做調(diào)整
- 為了不影響客戶端的訪問阴颖,主活喊、備機之間共享一個對客戶端來說唯一的地址,比如虛擬ip量愧,主機綁定這個虛擬ip
- 客戶端記錄主備機的地址钾菊,哪個能訪問就訪問哪個,備機也許可以收到客戶端的操作請求偎肃,但會以不提供服務的原因直接拒絕
這種直連的轉(zhuǎn)換形式簡單煞烫,缺點是狀態(tài)轉(zhuǎn)換通道本身有故障,則備機會認為主機故障從而將自身升級為主機累颂,如果恰好主機沒故障滞详,則變成了兩個主機。通過增加狀態(tài)轉(zhuǎn)換通道的方式可降低故障概率紊馏,但無法降為0料饥,甚至可能從不同的轉(zhuǎn)換通道收到不同甚至矛盾的信息。
中介式
在主備之間引入第三方中介朱监,主備都連中介岸啡,并通過中介傳遞狀態(tài)信息,架構如圖
中介式架構有如下特點
- 連接管理更簡單
不在需要建立和管理狀態(tài)連接通道赫编,只需連接中介凰狞,降低了管理復雜度。 - 狀態(tài)決策簡單
主備機無需通過判斷連接通道的狀態(tài)信息做決策沛慢,只需要傳遞信息給中介并根據(jù)如下規(guī)則判斷- 主赡若、備機的初始狀態(tài)都是備機,且只要與中介斷開連接就降為備機团甲,可能出現(xiàn)雙備機情況
- 主機與中介斷開連接逾冬,中介通知備機該信息,備機升級為主機
- 網(wǎng)絡中斷導致主機與中介斷開連接,主機降為備機身腻,網(wǎng)絡恢復后产还,舊的主機以新的備機身份向中介上報狀態(tài)
- 若掉電重啟或進程重啟,舊主機變?yōu)閭錂C嘀趟,與中介恢復連接脐区,發(fā)現(xiàn)有了主機,則保持備機狀態(tài)不變
- 主備機與中介連接都正常她按,按其他情況決定是否轉(zhuǎn)換牛隅,比如主機響應時間超過3秒,則進行轉(zhuǎn)換酌泰,主機降為備機媒佣,備機升為主機
這種架構的成本是中介機器本身就是高可用的機器,如果中介崩潰陵刹,則整個系統(tǒng)面臨崩潰的局面默伍。
mongoDB的replica set采取的就是中介式架構。
中介式架構中的中介可以通過ZooKeeper來實現(xiàn)衰琐,這個開源項目實現(xiàn)了統(tǒng)一命名服務也糊、狀態(tài)同步服務、集群管理羡宙、分布式應用配置項的管理等显设,且它本身也是高可用系統(tǒng)。
模擬式
主備機之間不傳遞任何狀態(tài)數(shù)據(jù)辛辨,而備機模擬成一個客戶端捕捂,向主機發(fā)起模擬讀寫操作,根據(jù)讀寫操作的響應情況來判斷主機的狀態(tài)斗搞。
架構如圖
模擬式的架構實現(xiàn)簡單指攒,無需狀態(tài)傳遞通道的建立和管理。不過缺點在于備機獲得的狀態(tài)信息只有應用層的響應信息僻焚,沒有互連式的多樣化信息允悦,如CPU負載,IO負載虑啤,吞吐量隙弛、響應時間等的信息,用于做決策的信息很有限狞山。
主主復制
兩臺主機都是主機全闷,互相備份數(shù)據(jù)給對方,客戶端任一挑選一個機器做讀寫操作萍启,架構如圖
業(yè)務上需要考慮的風險是主機1在故障后無法恢復总珠,寫入該主機但沒有復制的給主機2的數(shù)據(jù)會丟失屏鳍,需人工排查和恢復,有的數(shù)據(jù)可能永遠丟失局服。另一個需要考慮的點是寫入1的機器從2中因復制延遲無法瞬時讀取钓瞭。
主主模式無需倒換和區(qū)分不同的角色∫迹看起來簡單山涡,但架構不簡單,表現(xiàn)為要保證數(shù)據(jù)能夠雙向復制唆迁,但很多數(shù)據(jù)可能無法雙向復制鸭丛,比如
- auto increment的用戶id,在1號主機創(chuàng)建媒惕,為200,則此時2號主機創(chuàng)建id則要跳過200
- 主機1的庫存是300来庭,連續(xù)賣掉兩件妒蔚,庫存298,主機2的庫存賣掉1件月弛,變?yōu)?99肴盏,此時主機1數(shù)據(jù)復制到2,2的庫存變?yōu)?98
主主模式對數(shù)據(jù)的設計有要求,一般適用于臨時性帽衙、可丟失菜皂、可覆蓋的數(shù)據(jù)場景,如用戶登錄產(chǎn)生的session(可重新登錄生成)厉萝,用戶行為日志(可丟)恍飘,論壇草稿(可丟).
(2022.06.29 Wed)
數(shù)據(jù)分區(qū)
這里的分區(qū)指的是按一定的規(guī)則在地理上的分去,每個分區(qū)存儲一部分數(shù)據(jù)谴垫,規(guī)避地理級別的故障造成的巨大影響章母。設計分區(qū)需要考慮如下方面。
數(shù)據(jù)量
數(shù)據(jù)量過大翩剪,則分區(qū)規(guī)則越復雜乳怎,考慮的情況越多。
分區(qū)規(guī)則
地理位置決定不同的分區(qū)規(guī)則前弯,比如按大洲分區(qū)蚪缀,國家城市時區(qū)等等分區(qū)。
大洲分區(qū)面向不同大洲提供服務恕出,國家等以此類推询枚。
復制規(guī)則
為應對數(shù)據(jù)的災難情況,需要數(shù)據(jù)的復制浙巫,有下面三種情況
- 集中式
不同分區(qū)的數(shù)據(jù)存在一個中心數(shù)據(jù)中心上哩盲。結(jié)構簡單,分區(qū)之間無直接通信;擴展容易廉油;成本較高惠险,需要建立一個獨立的備份中心。
*互備式
每個分區(qū)備份另外一個分區(qū)的數(shù)據(jù)抒线。設計比較復雜班巩,每個分去都要承擔數(shù)據(jù)存儲和承擔備份功能,相互之間要關聯(lián)和影響嘶炭;擴展麻煩抱慌;成本低,直接使用已有的設備眨猎。 - 獨立式
每個分區(qū)有獨立的備份中心抑进,注意保證分區(qū)和備份之間的地理距離,保證電力或天氣等因素對兩處地點的影響最小睡陪。設計簡單寺渗,分區(qū)不影響;擴展容易兰迫;成本高信殊。
數(shù)據(jù)集群
集群是多臺及其組合在一起形成統(tǒng)一的系統(tǒng),數(shù)量至少是3臺汁果。根據(jù)機器承擔的不同角色劃分污秆,集群分為兩類耕驰,數(shù)據(jù)集中集群场刑、數(shù)據(jù)分散集群蔽豺。
數(shù)據(jù)集中集群
所謂數(shù)據(jù)集中,指的是集群結(jié)構為一主多備/從棘利,數(shù)據(jù)只能在主機中寫汞窗,讀操作可以主也可以從備/從,根據(jù)主備赡译、主從架構靈活應變仲吏。
復雜度提高,相比于一主一備/從架構蝌焚,主要體現(xiàn)在:
- 主機復制數(shù)據(jù)給備機
一主一備/從的架構中裹唆,只有一條復制通道,而數(shù)據(jù)集群中有多條這樣的通道只洒。多通道增大主機復制的壓力许帐,需考慮降低主機復制壓力、降低主機復制給正常讀寫帶來的壓力
多通道可能導致多個備機之間數(shù)據(jù)不一致毕谴,可能需要對備機之間的數(shù)據(jù)一致性進行檢查和修正成畦,ZooKeeper在重新選舉Leader后會進入恢復狀態(tài) - 備機檢測主機狀態(tài)的方式
多臺備機需要對主機狀態(tài)進行判斷距芬,而不同的備機判斷的結(jié)果可能是不同的,處理這些不同的判斷較為棘手 - 主機故障后如何決定新主機
備機之間需要協(xié)調(diào)
目前集中式集群ZooKeeper為典型循帐,通過ZAB協(xié)議來解決上述問題框仔,但ZAB協(xié)議復雜,實現(xiàn)難度高拄养。
數(shù)據(jù)分散集群
分散集群指多個服務器組成的集群中每臺服務器負責存儲一部分數(shù)據(jù)离斩,每個服務器又會備份一部分數(shù)據(jù)。
分配數(shù)據(jù)到不同的服務器上的算法需要考慮如下方面:
- 均衡性
保證數(shù)據(jù)分區(qū)基本是均衡的瘪匿,不能存在多于幾倍的情況 - 容錯性
當部分服務故障時跛梗,需要將原來分配給故障服務器的數(shù)據(jù)分區(qū)分配給其他服務器 - 可伸縮性
擴充新的服務器之后,需要能夠自動將部分數(shù)據(jù)遷移到新服務器棋弥,并保證擴容性的均衡性
分區(qū)集群中每臺服務器都可以處理讀寫請求核偿,不存在集中集群中負責寫主機那樣的角色。在分區(qū)集群中顽染,需要有一臺來處理數(shù)據(jù)分配算法漾岳,這個機器可以是獨立的一臺,也可以是集群選舉出來的家乘。如果是選舉得到蝗羊,這臺機器一般被稱為主機藏澳,不過這個主機和數(shù)據(jù)集中集群中的主機在職責上并不相同仁锯。
Hadoop的實現(xiàn)是獨立的服務器負責數(shù)據(jù)分區(qū)的分配,叫做Namenode翔悠。其他節(jié)點稱為datanode业崖。
HDFS采用master/slave(primary/secondary)架構。一個HDFS集群由一個namenode和多個datanode組成蓄愁,namenode是中心服務器双炕,負責管理文件系統(tǒng)的名字空間,及客戶端對文件的訪問撮抓。datanode一般是一個節(jié)點一個妇斤,負責管理所在節(jié)點的存儲。用戶在HDFS上能夠以文件的形式存儲數(shù)據(jù)丹拯。一個文件被分成多個數(shù)據(jù)塊站超,這些塊存儲在一組datanode上。namenode執(zhí)行文件系統(tǒng)的名字空間操作乖酬,如打開死相、關閉、重命名文件或目錄咬像,也負責確定數(shù)據(jù)塊到具體datanode節(jié)點的映射算撮。datanode負責處理文件系統(tǒng)客戶端的讀寫請求生宛。在namenode的統(tǒng)一調(diào)度下進行數(shù)據(jù)塊的創(chuàng)建、刪除和復制肮柜。
ElasticSearch集群選舉一臺服務器做數(shù)據(jù)分區(qū)的分配陷舅,稱為master node。
數(shù)據(jù)集中集群素挽,client只能將數(shù)據(jù)寫到主機蔑赘;數(shù)據(jù)分散集群,client可以向集群中任意服務器讀寫數(shù)據(jù)预明。這種差異決定了應用場景缩赛。集中式適合數(shù)據(jù)量不大,集群機器數(shù)量不多的場景撰糠,如ZooKeeper集群酥馍,機器一般5臺;分散式集群阅酪,因其良好的可擴展性旨袒,事業(yè)業(yè)務數(shù)據(jù)量大,集群機器龐大的業(yè)務場景术辐,如Hadoop集群砚尽,HBase集群。
分布式事務算法
有的業(yè)務場景需要事務來保證數(shù)據(jù)一致性辉词,采用集群方案必孤,數(shù)據(jù)可能分布在不同的集群節(jié)點上,節(jié)點間只能靠消息進行通信瑞躺,因此分布式事務實現(xiàn)起來只能依賴消息通知敷搪,而消息有可能丟失,這帶來了復雜性幢哨。
下面分別介紹事務算法中的二階段提交(two-phase commit protocol, 2PC)和三階段提交(3PC)赡勘。
2PC
2PC由兩階段組成,分別是Commit請求階段和Commit提交階段捞镰。
該算法有如下假設:
- 分布式系統(tǒng)中闸与,存在一個節(jié)點作為協(xié)調(diào)者(coordinator),其他節(jié)點作為參與者(cohorts)岸售,且節(jié)點之間可以進行網(wǎng)絡通信
- 所有節(jié)點采用預寫式日志践樱,日志被寫入后即保持在可靠的存儲設備上,即便節(jié)點損壞冰评,也不會導致日志數(shù)據(jù)丟失
- 所有節(jié)點不會永久性損壞映胁,即使損壞,仍然可以恢復
算法基本說明:
- 第一階段-提交請求階段甲雅,或投票階段解孙,各參與者投票是否要繼續(xù)接下來的提交操作
- 協(xié)調(diào)者向所有參與者發(fā)送Query to commit消息坑填,詢問是否可以執(zhí)行提交事務,并開始等待各參與者回應
- 參與者執(zhí)行詢問發(fā)起為止的所有事務操作弛姜,并將Undo信息和Redo信息寫入日志脐瑰,返回yes給消息協(xié)調(diào)者;如果參與者執(zhí)行失敗廷臼,則返回no給協(xié)調(diào)者
- 第二階段-提交執(zhí)行階段
成功
當協(xié)調(diào)者從所有參與者獲得的相應消息都是yes時
- 協(xié)調(diào)者向所有參與者翻出Commit的請求
- 參與者完成Commit操作苍在,并釋放在整個事務期間占用的資源
- 參與者向協(xié)調(diào)者發(fā)送ACK消息
- 協(xié)調(diào)者收到所有參與者反饋的ACK消息,完成事務
失敗-任一參與者在第一階段發(fā)回No荠商,或協(xié)調(diào)者第一階段的詢問超時無法獲得所有 - 協(xié)調(diào)者向所有參與者發(fā)出Rollback的請求
- 參與者利用之前寫入的Undo信息執(zhí)行回滾寂恬,釋放事務期間占用的資源
- 參與者向協(xié)調(diào)者發(fā)送ACK消息
- 協(xié)調(diào)者收到所有參與者反饋的ACK消息,取消事務
2PC的缺點
- 同步阻塞:兩方互相等待對方消息莱没,等待過程中節(jié)點處于阻塞狀態(tài)初肉,不能做其他事,若節(jié)點響應消息慢饰躲,則整個系統(tǒng)全部被拖慢牙咏,導致難以支持高并發(fā)的場景
- 狀態(tài)不一致:協(xié)調(diào)者在發(fā)出Commit后,某參與者并未收到這個消息嘹裂,其他參與者收到妄壶,則收到消息的參與者提交事務,未收到者超時后回滾事務寄狼,導致事務狀態(tài)不一致丁寄。協(xié)調(diào)者會發(fā)送ROLLBACK給參與者,但該條信息同樣存在丟失問題
- 單點故障:如果協(xié)調(diào)者故障例嘱,則參與者一直阻塞
3PC
三階段提交算法是針對二階段提交算法在的"單點故障"而提出的解決方案狡逢。通過二階段提交算法中的第一階段和第二階段之間插入一個新的階段"準備階段"宁舰,當協(xié)調(diào)者故障后拼卵,參與者可以通過超時提交來避免一直阻塞。
具體算法:
第一階段(提交判斷階段)
- 協(xié)調(diào)者向參與者發(fā)送canCommit消息蛮艰,詢問參與者是否可以提交事務
- 參與者收到canCommit消息后腋腮,判別自己是否可以提交該事務,如果可以執(zhí)行就返yes壤蚜,不可以則返回no
- 如果協(xié)調(diào)者收到人一個no或參與者超時即寡,則事務終止,同時會通知參與者終止事務袜刷,如果在超時時間內(nèi)收到所有yes聪富,則進入第二階段
第二階段(準備提交階段)
- 協(xié)調(diào)者發(fā)送preCommit消息給所有參與者,告訴參與者準備提交
- 參與者收到preCommit消息后著蟹,執(zhí)行事務操作墩蔓,將undo和redi信息記錄到事務日志中梢莽,然后返回ACK消息
第三階段(提交執(zhí)行階段)
- 協(xié)調(diào)者在接收到所有ACK消息后會發(fā)送doCommit,告訴參與者正式提交奸披;否則會給參與者終止消息昏名,事務回滾
- 參與者收到doCommit消息后提交事務,然后返回haveCommitted消息
- 如果參與者收到一個preCommit消息并返回ACK阵面,但等待doCommit消息超時(例如協(xié)調(diào)者崩潰或超時)轻局,參與者則會在超時后繼續(xù)提交事務
3PC避免了單點故障導致系統(tǒng)阻塞問題,也存在數(shù)據(jù)不一致問題
分布式一致算法
placeholder
Reference
1 從零開始學架構-照著做样刷,你也能成為架構師仑扑,李運華著,電子工業(yè)出版社