原文:www.cnblogs.com/luckcs/articles/11235559.html
1 概念
1.1 模型
節(jié)點
在具體的工程項目中伊诵,一個節(jié)點往往是一個操作系統(tǒng)上的進(jìn)程。在本文的模型中缠捌,認(rèn)為節(jié)點是一個完整的秃诵、不可分的整體东羹,如果某個程序進(jìn)程實際上由若干相對獨立部分構(gòu)成哈垢,則在模型中可以將一個進(jìn)程劃分為多個節(jié)點。
異常
機器宕機:機器宕機是最常見的異常之一祝沸。在大型集群中每日宕機發(fā)生的概率為千分之一左右矮烹,在實踐中,一臺宕機的機器恢復(fù)的時間通常認(rèn)為是24 小時罩锐,一般需要人工介入重啟機器奉狈。
網(wǎng)絡(luò)異常:消息丟失,兩片節(jié)點之間彼此完全無法通信涩惑,即出現(xiàn)了“網(wǎng)絡(luò)分化”仁期;消息亂序,有一定的概率不是按照發(fā)送時的順序依次到達(dá)目的節(jié)點竭恬,考慮使用序列號等機制處理網(wǎng)絡(luò)消息的亂序問題跛蛋,使得無效的、過期的網(wǎng)絡(luò)消息不影響系統(tǒng)的正確性痊硕;數(shù)據(jù)錯誤赊级;不可靠的TCP,TCP 協(xié)議為應(yīng)用層提供了可靠的岔绸、面向連接的傳輸服務(wù)理逊,但在分布式系統(tǒng)的協(xié)議設(shè)計中不能認(rèn)為所有網(wǎng)絡(luò)通信都基于TCP 協(xié)議則通信就是可靠的。TCP協(xié)議只能保證同一個TCP 鏈接內(nèi)的網(wǎng)絡(luò)消息不亂序盒揉,TCP 鏈接之間的網(wǎng)絡(luò)消息順序則無法保證晋被。
分布式三態(tài):如果某個節(jié)點向另一個節(jié)點發(fā)起RPC(Remote procedure call)調(diào)用,即某個節(jié)點A 向另一個節(jié)點B 發(fā)送一個消息预烙,節(jié)點B 根據(jù)收到的消息內(nèi)容完成某些操作墨微,并將操作的結(jié)果通過另一個消息返回給節(jié)點A,那么這個RPC 執(zhí)行的結(jié)果有三種狀態(tài):“成功”扁掸、“失敗”翘县、“超時(未知)”,稱之為分布式系統(tǒng)的三態(tài)谴分。
存儲數(shù)據(jù)丟失:對于有狀態(tài)節(jié)點來說锈麸,數(shù)據(jù)丟失意味著狀態(tài)丟失,通常只能從其他節(jié)點讀取牺蹄、恢復(fù)存儲的狀態(tài)忘伞。
異常處理原則:被大量工程實踐所檢驗過的異常處理黃金原則是:任何在設(shè)計階段考慮到的異常情況一定會在系統(tǒng)實際運行中發(fā)生,但在系統(tǒng)實際運行遇到的異常卻很有可能在設(shè)計時未能考慮沙兰,所以怒炸,除非需求指標(biāo)允許畴蹭,在系統(tǒng)設(shè)計時不能放過任何異常情況贷屎。
1.2 副本
副本(replica/copy)指在分布式系統(tǒng)中為數(shù)據(jù)或服務(wù)提供的冗余谋币。對于數(shù)據(jù)副本指在不同的節(jié)點上持久化同一份數(shù)據(jù),當(dāng)出現(xiàn)某一個節(jié)點的存儲的數(shù)據(jù)丟失時斋射,可以從副本上讀到數(shù)據(jù)育勺。數(shù)據(jù)副本是分布式系統(tǒng)解決數(shù)據(jù)丟失異常的唯一手段但荤。另一類副本是服務(wù)副本,指數(shù)個節(jié)點提供某種相同的服務(wù)涧至,這種服務(wù)一般并不依賴于節(jié)點的本地存儲腹躁,其所需數(shù)據(jù)一般來自其他節(jié)點。
副本協(xié)議是貫穿整個分布式系統(tǒng)的理論核心南蓬。
副本一致性
分布式系統(tǒng)通過副本控制協(xié)議纺非,使得從系統(tǒng)外部讀取系統(tǒng)內(nèi)部各個副本的數(shù)據(jù)在一定的約束條件下相同,稱之為副本一致性(consistency)蓖康。副本一致性是針對分布式系統(tǒng)而言的铐炫,不是針對某一個副本而言垒手。
強一致性(strong consistency):任何時刻任何用戶或節(jié)點都可以讀到最近一次成功更新的副本數(shù)據(jù)蒜焊。強一致性是程度最高的一致性要求,也是實踐中最難以實現(xiàn)的一致性科贬。
單調(diào)一致性(monotonic consistency):任何時刻泳梆,任何用戶一旦讀到某個數(shù)據(jù)在某次更新后的值,這個用戶不會再讀到比這個值更舊的值榜掌。單調(diào)一致性是弱于強一致性卻非常實用的一種一致性級別优妙。因為通常來說,用戶只關(guān)心從己方視角觀察到的一致性憎账,而不會關(guān)注其他用戶的一致性情況套硼。
會話一致性(session consistency):任何用戶在某一次會話內(nèi)一旦讀到某個數(shù)據(jù)在某次更新后的值,這個用戶在這次會話過程中不會再讀到比這個值更舊的值胞皱。會話一致性通過引入會話的概念邪意,在單調(diào)一致性的基礎(chǔ)上進(jìn)一步放松約束,會話一致性只保證單個用戶單次會話內(nèi)數(shù)據(jù)的單調(diào)修改反砌,對于不同用戶間的一致性和同一用戶不同會話間的一致性沒有保障雾鬼。實踐中有許多機制正好對應(yīng)會話的概念,例如php 中的session 概念宴树。
最終一致性(eventual consistency):最終一致性要求一旦更新成功策菜,各個副本上的數(shù)據(jù)最終將達(dá) 到完全一致的狀態(tài),但達(dá)到完全一致狀態(tài)所需要的時間不能保障酒贬。對于最終一致性系統(tǒng)而言又憨,一個用戶只要始終讀取某一個副本的數(shù)據(jù),則可以實現(xiàn)類似單調(diào)一致性的效果锭吨,但一旦用戶更換讀取的副本蠢莺,則無法保障任何一致性。
弱一致性(week consistency):一旦某個更新成功耐齐,用戶無法在一個確定時間內(nèi)讀到這次更新的值浪秘,且即使在某個副本上讀到了新的值蒋情,也不能保證在其他副本上可以讀到新的值。弱一致性系統(tǒng)一般很難在實際中使用耸携,使用弱一致性系統(tǒng)需要應(yīng)用方做更多的工作從而使得系統(tǒng)可用棵癣。
1.3 衡量分布式系統(tǒng)的指標(biāo)
性能:系統(tǒng)的吞吐能力,指系統(tǒng)在某一時間可以處理的數(shù)據(jù)總量夺衍,通潮芬辏可以用系統(tǒng)每秒處理的總的數(shù)據(jù)量來衡量;系統(tǒng)的響應(yīng)延遲沟沙,指系統(tǒng)完成某一功能需要使用的時間河劝;系統(tǒng)的并發(fā)能力,指系統(tǒng)可以同時完成某一功能的能力矛紫,通常也用QPS(query per second)來衡量赎瞎。上述三個性能指標(biāo)往往會相互制約,追求高吞吐的系統(tǒng)颊咬,往往很難做到低延遲务甥;系統(tǒng)平均響應(yīng)時間較長時,也很難提高QPS喳篇。
可用性:系統(tǒng)的可用性(availability)指系統(tǒng)在面對各種異常時可以正確提供服務(wù)的能力敞临。系統(tǒng)的可用性可以用系統(tǒng)停服務(wù)的時間與正常服務(wù)的時間的比例來衡量,也可以用某功能的失敗次數(shù)與成功次數(shù)的比例來衡量麸澜⊥δ颍可用性是分布式的重要指標(biāo),衡量了系統(tǒng)的魯棒性炊邦,是系統(tǒng)容錯能力的體現(xiàn)编矾。
可擴展性:系統(tǒng)的可擴展性(scalability)指分布式系統(tǒng)通過擴展集群機器規(guī)模提高系統(tǒng)性能(吞吐、延遲铣耘、并發(fā))洽沟、存儲容量、計算能力的特性蜗细。好的分布式系統(tǒng)總在追求“線性擴展性”裆操,也就是使得系統(tǒng)的某一指標(biāo)可以隨著集群中的機器數(shù)量線性增長。
一致性:分布式系統(tǒng)為了提高可用性炉媒,總是不可避免的使用副本的機制踪区,從而引發(fā)副本一致性的問題。越是強的一致的性模型吊骤,對于用戶使用來說使用起來越簡單缎岗。
2 分布式系統(tǒng)原理
2.1 數(shù)據(jù)分布方式
所謂分布式系統(tǒng)顧名思義就是利用多臺計算機協(xié)同解決單臺計算機所不能解決的計算、存儲等問題白粉。單機系統(tǒng)與分布式系統(tǒng)的最大的區(qū)別在于問題的規(guī)模传泊,即計算鼠渺、存儲的數(shù)據(jù)量的區(qū)別。將一個單機問題使用分布式解決眷细,首先要解決的就是如何將問題拆解為可以使用多機分布式解決拦盹,使得分布式系統(tǒng)中的每臺機器負(fù)責(zé)原問題的一個子集。由于無論是計算還是存儲溪椎,其問題輸入對象都是數(shù)據(jù)普舆,所以如何拆解分布式系統(tǒng)的輸入數(shù)據(jù)成為分布式系統(tǒng)的基本問題。
哈希方式
哈希分布數(shù)據(jù)的缺點同樣明顯校读,突出表現(xiàn)為可擴展性不高沼侣,一旦集群規(guī)模需要擴展,則幾乎所有的數(shù)據(jù)需要被遷移并重新分布歉秫。工程中蛾洛,擴展哈希分布數(shù)據(jù)的系統(tǒng)時,往往使得集群規(guī)模成倍擴展端考,按照數(shù)據(jù)重新計算哈希雅潭,這樣原本一臺機器上的數(shù)據(jù)只需遷移一半到另一臺對應(yīng)的機器上即可完成擴展。
針對哈希方式擴展性差的問題却特,一種思路是不再簡單的將哈希值與機器做除法取模映射,而是將對應(yīng)關(guān)系作為元數(shù)據(jù)由專門的元數(shù)據(jù)服務(wù)器管理.同時筛圆,哈希值取模個數(shù)往往大于機器個數(shù)裂明,這樣同一臺機器上需要負(fù)責(zé)多個哈希取模的余數(shù)。但需要以較復(fù)雜的機制維護(hù)大量的元數(shù)據(jù)太援。哈希分布數(shù)據(jù)的另一個缺點是闽晦,一旦某數(shù)據(jù)特征值的數(shù)據(jù)嚴(yán)重不均,容易出現(xiàn)“數(shù)據(jù)傾斜”(data skew)問題提岔。
哈希分布數(shù)據(jù)的另一個缺點是仙蛉,一旦某數(shù)據(jù)特征值的數(shù)據(jù)嚴(yán)重不均,容易出現(xiàn)“數(shù)據(jù)傾斜”(data skew)問題
按數(shù)據(jù)范圍分布
按數(shù)據(jù)范圍分布是另一個常見的數(shù)據(jù)分布式碱蒙,將數(shù)據(jù)按特征值的值域范圍劃分為不同的區(qū)間荠瘪,使得集群中每臺(組)服務(wù)器處理不同區(qū)間的數(shù)據(jù)。
工程中赛惩,為了數(shù)據(jù)遷移等負(fù)載均衡操作的方便哀墓,往往利用動態(tài)劃分區(qū)間的技術(shù),使得每個區(qū)間中服務(wù)的數(shù)據(jù)量盡量的一樣多喷兼。當(dāng)某個區(qū)間的數(shù)據(jù)量較大時篮绰,通過將區(qū)間“分裂”的方式拆分為兩個區(qū)間,使得每個數(shù)據(jù)區(qū)間中的數(shù)據(jù)量都盡量維持在一個較為固定的閾值之下季惯。
一般的吠各,往往需要使用專門的服務(wù)器在內(nèi)存中維護(hù)數(shù)據(jù)分布信息臀突,稱這種數(shù)據(jù)的分布信息為一種元信息。甚至對于大規(guī)模的集群贾漏,由于元信息的規(guī)模非常龐大惧辈,單臺 計算機無法獨立維護(hù),需要使用多臺機器作為元信息服務(wù)器磕瓷。
按數(shù)據(jù)量分布
數(shù)據(jù)量分布數(shù)據(jù)與具體的數(shù)據(jù)特征無關(guān)盒齿,而是將數(shù)據(jù)視為一個順序增長的文件,并將這個文件按照某一較為固定的大小劃分為若干數(shù)據(jù)塊(chunk)困食,不同的數(shù)據(jù)塊分布到不同的服務(wù)器上边翁。與按數(shù)據(jù)范圍分布數(shù)據(jù)的方式類似的是,按數(shù)據(jù)量分布數(shù)據(jù)也需要記錄數(shù)據(jù)塊的具體分布情況硕盹,并將該分布信息作為元數(shù)據(jù)使用元數(shù)據(jù)服務(wù)器管理符匾。
由于與具體的數(shù)據(jù)內(nèi)容無關(guān),按數(shù)據(jù)量分布數(shù)據(jù)的方式一般沒有數(shù)據(jù)傾斜的問題瘩例,數(shù)據(jù)總是被均勻切分并分布到集群中啊胶。當(dāng)集群需要重新負(fù)載均衡時,只需通過遷移數(shù)據(jù)塊即可完成垛贤。集群擴容也沒有太大的限制焰坪,只需將部分?jǐn)?shù)據(jù)庫遷移到新加入的機器上即可以完成擴容。按數(shù)據(jù)量劃分?jǐn)?shù)據(jù)的缺點是需要管理較為復(fù)雜的元信息聘惦,與按范圍分布數(shù)據(jù)的方式類似某饰,當(dāng)集群規(guī)模較大時,元信息的數(shù)據(jù)量也變得很大善绎,高效的管理元信息成為新的課題黔漂。
一致性哈希
一致性哈希(consistent hashing)是另一個種在工程中使用較為廣泛的數(shù)據(jù)分布方式。一致性哈希最初在P2P 網(wǎng)絡(luò)中作為分布式哈希表(DHT)的常用數(shù)據(jù)分布算法禀酱。一致性哈希的基本方式是使用一個哈希函數(shù)計算數(shù)據(jù)或數(shù)據(jù)特征的哈希值炬守,令該哈希函數(shù)的輸出值域為一個封閉的環(huán),即哈希函數(shù)輸出的最大值是最小值的前序剂跟。將節(jié)點隨機分布到這個環(huán)上减途,每個節(jié)點負(fù)責(zé)處理從自己開始順時針至下一個節(jié)點的全部哈希值域上的數(shù)據(jù)。
使用一致性哈希的方式需要將節(jié)點在一致性哈希環(huán)上的位置作為元信息加以管理浩聋,這點比直接使用哈希分布數(shù)據(jù)的方式要復(fù)雜观蜗。然而,節(jié)點的位置信息只于集群中的機器規(guī)模相關(guān)衣洁,其元信息的量通常比按數(shù)據(jù)范圍分布數(shù)據(jù)和按數(shù)據(jù)量分布數(shù)據(jù)的元信息量要小很多墓捻。
為此一種常見的改進(jìn)算法是引入虛節(jié)點(virtual node)的概念,系統(tǒng)初始時就創(chuàng)建許多虛節(jié)點,虛節(jié)點的個數(shù)一般遠(yuǎn)大于未來集群中機器的個數(shù)砖第,將虛節(jié)點均勻分布到一致性哈希值域環(huán)上撤卢,其功能與基本一致性哈希算法中的節(jié)點相同。為每個節(jié)點分配若干虛節(jié)點梧兼。操作數(shù)據(jù)時放吩,首先通過數(shù)據(jù)的哈希值在環(huán)上找到對應(yīng)的虛節(jié)點,進(jìn)而查找元數(shù)據(jù)找到對應(yīng)的真實節(jié)點羽杰。使用虛節(jié)點改進(jìn)有多個優(yōu)點渡紫。首先,一旦某個節(jié)點不可用考赛,該節(jié)點將使得多個虛節(jié)點不可用惕澎,從而使得多個相鄰的真實節(jié)點負(fù)載失效節(jié)點的壓里。同理颜骤,一旦加入一個新節(jié)點唧喉,可以分配多個虛節(jié)點,從而使得新節(jié)點可以 負(fù)載多個原有節(jié)點的壓力忍抽,從全局看八孝,較容易實現(xiàn)擴容時的負(fù)載均衡。
副本與數(shù)據(jù)分布
分布式系統(tǒng)容錯鸠项、提高可用性的基本手段就是使用副本干跛。對于數(shù)據(jù)副本的分布方式主要影響系統(tǒng)的可擴展性。一種基本的數(shù)據(jù)副本策略是以機器為單位锈锤,若干機器互為副本驯鳖,副本機器之間的數(shù)據(jù)完全相同。這種策略適用于上述各種數(shù)據(jù)分布方式久免。其優(yōu)點是非常簡單,其缺點是恢復(fù)數(shù)據(jù)的效率不高扭弧、可擴展性也不高阎姥。
更合適的做法不是以機器作為副本單位,而是將數(shù)據(jù)拆為較合理的數(shù)據(jù)段鸽捻,以數(shù)據(jù)段為單位作為副本呼巴。實踐中,常常使得每個數(shù)據(jù)段的大小盡量相等且控制在一定的大小以內(nèi)喇聊。數(shù)據(jù)段有很多不同的稱謂签财,segment画拾,fragment,chunk府瞄,partition 等等。數(shù)據(jù)段的選擇與數(shù)據(jù)分布方式直接相關(guān)碘箍。對于哈希分?jǐn)?shù)據(jù)的方式遵馆,每個哈希分桶后的余數(shù)可以作為一個數(shù)據(jù)段鲸郊,為了控制數(shù)據(jù)段的大小,常常使得分桶個數(shù)大于集群規(guī)模货邓。一旦將數(shù)據(jù)分為數(shù)據(jù)段秆撮,則可以以數(shù)據(jù)段為單位管理副本,從而副本與機器不再硬相關(guān)换况,每臺機器都可以負(fù)責(zé)一定數(shù)據(jù)段的副本职辨。
一旦副本分布與機器無關(guān),數(shù)據(jù)丟失后的恢復(fù)效率將非常高戈二。這是因為舒裤,一旦某臺機器的數(shù)據(jù)丟失,其上數(shù)據(jù)段的副本將分布在整個集群的所有機器中挽拂,而不是僅在幾個副本機器中惭每,從而可以從整個集群同時拷貝恢復(fù)數(shù)據(jù),而集群中每臺數(shù)據(jù)源機器都可以以非常低的資源做拷貝亏栈。作為恢復(fù)數(shù)據(jù)源的機器即使都限速1MB/s台腥,若有100 臺機器參與恢復(fù),恢復(fù)速度也能達(dá)到100MB/s绒北。再者黎侈,副本分布與機器無關(guān)也利于集群容錯。如果出現(xiàn)機器宕機闷游,由于宕機機器上的副本分散于整個集群峻汉,其壓力也自然分散到整個集群。最后脐往,副本分布與機器無關(guān)也利于集群擴展休吠。理論上,設(shè)集群規(guī)模 為N 臺機器业簿,當(dāng)加入一臺新的機器時瘤礁,只需從各臺機器上遷移1/N – 1/N+1 比例的數(shù)據(jù)段到新機器即實現(xiàn)了新的負(fù)載均衡。由于是從集群中各機器遷移數(shù)據(jù)梅尤,與數(shù)據(jù)恢復(fù)同理柜思,效率也較高。工程中巷燥,完全按照數(shù)據(jù)段建立副本會引起需要管理的元數(shù)據(jù)的開銷增大赡盘,副本維護(hù)的難度也相應(yīng)增大。一種折中的做法是將某些數(shù)據(jù)段組成一個數(shù)據(jù)段分組缰揪,按數(shù)據(jù)段分組為粒度進(jìn)行副本管理陨享。這樣做可以將副本粒度控制在一個較為合適的范圍內(nèi)。
本地化計算
在分布式系統(tǒng)中,數(shù)據(jù)的分布方式也深深影響著計算的分布方式霉咨。在分布式系統(tǒng)中計算節(jié)點和保存計算數(shù)據(jù)的存儲節(jié)點可以在同一臺物理機器上蛙紫,也可以位于不同的物理機器。如果計算節(jié)點和存儲節(jié)點位于不同的物理機器則計算的數(shù)據(jù)需要通過網(wǎng)絡(luò)傳輸途戒,此種方式的開銷很大坑傅,甚至網(wǎng)絡(luò)帶寬會成為系統(tǒng)的總體瓶頸。另一種思路是喷斋,將計算盡量調(diào)度到與存儲節(jié)點在同一臺物理機器上的計算節(jié)點上進(jìn)行唁毒,這稱之為本地化計算。本地化計算是計算調(diào)度的一種重要優(yōu)化星爪,其體現(xiàn)了一種重要的分布式調(diào)度思想:“移動數(shù)據(jù)不如移動計算”浆西。
數(shù)據(jù)分布方式的選擇
在實際工程實踐中,可以根據(jù)需求及實施復(fù)雜度合理選擇數(shù)據(jù)分布方式顽腾。另外近零,數(shù)據(jù)分布方式是可以靈活組合使用的,往往可以兼?zhèn)涓鞣N方式的優(yōu)點抄肖,收到較好的綜合效果久信。
例:數(shù)據(jù)傾斜問題,在按哈希分?jǐn)?shù)據(jù)的基礎(chǔ)上引入按數(shù)據(jù)量分布數(shù)據(jù)的方式漓摩,解決該數(shù)據(jù)傾斜問題裙士。按用戶id 的哈希值分?jǐn)?shù)據(jù),當(dāng)某個用戶id 的數(shù)據(jù)量特別大時管毙,該用戶的數(shù)據(jù)始終落在某一臺機器上腿椎。此時,引入按數(shù)據(jù)量分布數(shù)據(jù)的方式夭咬,統(tǒng)計用戶的數(shù)據(jù)量啃炸,并按某一閾值將用戶的數(shù)據(jù)切為多個均勻的數(shù)據(jù)段,將這些數(shù)據(jù)段分布到集群中去卓舵。由于大部分用戶的數(shù)據(jù)量不會超過閾值肮帐,所以元數(shù)據(jù)中僅僅保存超過閾值的用戶的數(shù)據(jù)段分布信息,從而可以控制元數(shù)據(jù)的規(guī)模边器。這種哈希分布數(shù)據(jù)方式與按數(shù)據(jù)量分布數(shù)據(jù)方式組合使用的方案,在某真實系統(tǒng)中使用托修,取得了較好的效果忘巧。
2.2 基本副本協(xié)議
副本控制協(xié)議指按特定的協(xié)議流程控制副本數(shù)據(jù)的讀寫行為,使得副本滿足一定的可用性和一致性要求的分布式協(xié)議睦刃。副本控制協(xié)議要具有一定的對抗異常狀態(tài)的容錯能力砚嘴,從而使得系統(tǒng)具有一定的可用性,同時副本控制協(xié)議要能提供一定一致性級別。由CAP 原理(在2.9 節(jié)詳細(xì)分析)可知际长,要設(shè)計一種滿足強一致性耸采,且在出現(xiàn)任何網(wǎng)絡(luò)異常時都可用的副本協(xié)議是不可能的。為此工育,實際中的副本控制協(xié)議總是在可用性虾宇、一致性與性能等各要素之間按照具體需求折中。
副本控制協(xié)議可以分為兩大類:“中心化(centralized)副本控制協(xié)議”和“去中心化(decentralized)副本控制協(xié)議”如绸。
中心化副本控制協(xié)議
中心化副本控制協(xié)議的基本思路是由一個中心節(jié)點協(xié)調(diào)副本數(shù)據(jù)的更新嘱朽、維護(hù)副本之間的一致性。圖給出了中心化副本協(xié)議的通用架構(gòu)怔接。中心化副本控制協(xié)議的優(yōu)點是協(xié)議相對較為簡單搪泳,所有的副本相關(guān)的控制交由中心節(jié)點完成。并發(fā)控制將由中心節(jié)點完成扼脐,從而使得一個分布式并發(fā)控制問題岸军,簡化為一個單機并發(fā)控制問題。所謂并發(fā)控制瓦侮,即多個節(jié)點同時需要修改副本數(shù)據(jù)時艰赞,需要解決“寫寫”、“讀寫”等并發(fā)沖突脏榆。單機系統(tǒng)上常用加鎖等方式進(jìn)行并發(fā)控制猖毫。對于分布式并發(fā)控制,加鎖也是一個常用的方法须喂,但如果沒有中心節(jié)點統(tǒng)一進(jìn)行鎖管理吁断,就需要完全分布式化的鎖系統(tǒng),會使得協(xié)議非常復(fù)雜坞生。中心化副本控制協(xié)議的缺點是系統(tǒng)的可用性依賴于中心化節(jié)點仔役,當(dāng)中心節(jié)點異常或與中心節(jié)點通信中斷時是己,系統(tǒng)將失去某些服務(wù)(通常至少失去更新服務(wù))又兵,所以中心化副本控制協(xié)議的缺點正是存在一定的停服務(wù)時間。
primary-secondary 協(xié)議
在primary-secondary 類型的協(xié)議中卒废,副本被分為兩大類沛厨,其中有且僅有一個副本作為primary 副本,除primary 以外的副本都作為secondary 副本摔认。維護(hù)primary 副本的節(jié)點作為中心節(jié)點逆皮,中心節(jié)點負(fù)責(zé)維護(hù)數(shù)據(jù)的更新、并發(fā)控制参袱、協(xié)調(diào)副本的一致性电谣。
Primary-secondary 類型的協(xié)議一般要解決四大類問題:數(shù)據(jù)更新流程秽梅、數(shù)據(jù)讀取方式、Primary 副本的確定和切換剿牺、數(shù)據(jù)同步(reconcile)企垦。
數(shù)據(jù)更新基本流程
數(shù)據(jù)更新都由primary 節(jié)點協(xié)調(diào)完成。
外部節(jié)點將更新操作發(fā)給primary 節(jié)點
primary 節(jié)點進(jìn)行并發(fā)控制即確定并發(fā)更新操作的先后順序
primary 節(jié)點將更新操作發(fā)送給secondary 節(jié)點
primary 根據(jù)secondary 節(jié)點的完成情況決定更新是否成功并將結(jié)果返回外部節(jié)點
在工程實踐中晒来,如果由primary 直接同時發(fā)送給其他N 個副本發(fā)送數(shù)據(jù)钞诡,則每個 secondary 的更新吞吐受限于primary 總的出口網(wǎng)絡(luò)帶寬,最大為primary 網(wǎng)絡(luò)出口帶寬的1/N潜索。為了解決這個問題臭增,有些系統(tǒng)(例如,GFS)竹习,使用接力的方式同步數(shù)據(jù)誊抛,即primary 將更新發(fā)送給第一 個secondary 副本,第一個secondary 副本發(fā)送給第二secondary 副本整陌,依次類推拗窃。
數(shù)據(jù)讀取方式
數(shù)據(jù)讀取方式也與一致性高度相關(guān)。如果只需要最終一致性泌辫,則讀取任何副本都可以滿足需求随夸。如果需要會話一致性,則可以為副本設(shè)置版本號震放,每次更新后遞增版本號宾毒,用戶讀取副本時驗證版本號,從而保證用戶讀到的數(shù)據(jù)在會話范圍內(nèi)單調(diào)遞增殿遂。使用primary-secondary 比較困難的是實現(xiàn)強一致性诈铛。
- 由于數(shù)據(jù)的更新流程都是由primary 控制的,primary 副本上的數(shù)據(jù)一定是最新的墨礁,所以 如果始終只讀primary 副本的數(shù)據(jù)幢竹,可以實現(xiàn)強一致性。如果只讀primary 副本恩静,則secondary 副本將不提供讀服務(wù)焕毫。實踐中,如果副本不與機器綁定驶乾,而是按照數(shù)據(jù)段為單位維護(hù)副本邑飒,僅有primary 副本提供讀服務(wù)在很多場景下并不會造出機器資源浪費。
將副本分散到集群中個级乐,假設(shè)primary 也是隨機的確定的幸乒,那么每臺機器上都有一些數(shù)據(jù)的primary 副本,也有另一些數(shù)據(jù)段的secondary 副本唇牧。從而某臺服務(wù)器實際都提供讀寫服務(wù)罕扎。
- 由primary 控制節(jié)點secondary 節(jié)點的可用性。當(dāng)primary 更新某個secondary 副本不成功時丐重,primary 將該secondary 副本標(biāo)記為不可用腔召,從而用戶不再讀取該不可用的副本。不可用的 secondary 副本可以繼續(xù)嘗試與primary 同步數(shù)據(jù)扮惦,當(dāng)與primary 完成數(shù)據(jù)同步后臀蛛,primary 可以副本標(biāo)記為可用。這種方式使得所有的可用的副本崖蜜,無論是primary 還是secondary 都是可讀的浊仆,且在一個確定的時間內(nèi),某secondary 副本要么更新到與primary 一致的最新狀態(tài)豫领,要么被標(biāo)記為不可用抡柿,從而符合較高的一致性要求。這種方式依賴于一個中心元數(shù)據(jù)管理系統(tǒng)等恐,用于記錄哪些副本可用洲劣,哪些副本不可用。某種意義上课蔬,該方式通過降低系統(tǒng)的可用性來提高系統(tǒng)的一致性囱稽。
primary 副本的確定與切換
在primary-secondary 類型的協(xié)議中,另一個核心的問題是如何確定primary 副本二跋,尤其是在原primary 副本所在機器出現(xiàn)宕機等異常時战惊,需要有某種機制切換primary 副本,使得某個secondary 副本成為新的primary 副本扎即。
通常的吞获,在primary-secondary 類型的分布式系統(tǒng)中,哪個副本是primary 這一信息都屬于元信息铺遂,由專門的元數(shù)據(jù)服務(wù)器維護(hù)衫哥。執(zhí)行更新操作時,首先查詢元數(shù)據(jù)服務(wù)器獲取副本的primary 信息襟锐,從而進(jìn)一步執(zhí)行數(shù)據(jù)更新流程撤逢。
由于分布式系統(tǒng)中可靠的發(fā)現(xiàn)節(jié)點異常是需要一定的探測時間的,這樣的探測時間通常是10 秒級別粮坞,這也意味著一旦primary 異常蚊荣,最多需要10 秒級別的發(fā)現(xiàn)時間,系統(tǒng)才能開始primary 的切換莫杈,在這10 秒時間內(nèi)互例,由于沒有primary,系統(tǒng)不能提供更 新服務(wù)筝闹,如果系統(tǒng)只能讀primary 副本媳叨,則這段時間內(nèi)甚至不能提供讀服務(wù)腥光。從這里可以看到,primary-backup 類副本協(xié)議的最大缺點就是由于primary 切換帶來的一定的停服務(wù)時間糊秆。
數(shù)據(jù)同步
不一致的secondary 副本需要與primary 進(jìn)行同步(reconcile)武福。
通常不一致的形式有三種:一、由于網(wǎng)絡(luò)分化等異常痘番,secondary 上的數(shù)據(jù)落后于primary 上的數(shù)據(jù)捉片。二、在某些協(xié)議下,secondary 上的數(shù)據(jù)有可能是臟數(shù)據(jù),需要被丟棄碰煌。所謂臟數(shù)據(jù)是由于primary 副本沒有進(jìn)行某一更新操作念脯,而secondary 副本上反而進(jìn)行的多余的修改操作,從而造成secondary 副本數(shù)據(jù)錯誤。三、secondary 是一個新增加的副本,完全沒有數(shù)據(jù)访惜,需要從其他副本上拷貝數(shù)據(jù)。
對于第一種secondary 數(shù)據(jù)落后的情況腻扇,常見的同步方式是回放primary 上的操作日志(通常是redo 日志)债热,從而追上primary 的更新進(jìn)度。對于臟數(shù)據(jù)的情況幼苛,較好的做法是設(shè)計的分布式協(xié)議不產(chǎn)生臟數(shù)據(jù)窒篱。如果協(xié)議一定有產(chǎn)生臟數(shù)據(jù)的可能,則也應(yīng)該使得產(chǎn)生臟數(shù)據(jù)的概率降到非常低得情況舶沿,從而一旦發(fā)生臟數(shù)據(jù)的情況可以簡單的直接丟棄有臟數(shù)據(jù)的副本墙杯,這樣相當(dāng)于副本沒有數(shù)據(jù)。另外括荡,也可以設(shè)計一些基于undo 日志的方式從而可以刪除臟數(shù)據(jù)高镐。如果secondary 副本完全沒有數(shù)據(jù),則常見的做法是直接拷貝primary 副本的數(shù)據(jù)畸冲,這種方法往往比回放日志追更新進(jìn)度的方法快很多嫉髓。但拷貝數(shù)據(jù)時primary 副本需要能夠繼續(xù)提供更新服務(wù),這就要求primary 副本支持快照(snapshot)功能邑闲。即對某一刻的副本數(shù)據(jù)形成快照算行,然后拷貝快照,拷貝完成后使用回放日志的方式追快照形成后的更新操作苫耸。
去中心化副本控制協(xié)議
去中心化副本控制協(xié)議沒有中心節(jié)點州邢,協(xié)議中所有的節(jié)點都是完全對等的,節(jié)點之間通過平等協(xié)商達(dá)到一致褪子。從而去中心化協(xié)議沒有因為中心化節(jié)點異常而帶來的停服務(wù)等問題量淌。
去中心化協(xié)議的最大的缺點是協(xié)議過程通常比較復(fù)雜骗村。尤其當(dāng)去中心化協(xié)議需要實現(xiàn)強一致性時,協(xié)議流程變得復(fù)雜且不容易理解类少。由于流程的復(fù)雜叙身,去中心化協(xié)議的效率或者性能一般也較中心化協(xié)議低。一個不恰當(dāng)?shù)谋确骄褪橇蚰行幕北究刂茀f(xié)議類似專制制度,系統(tǒng)效率高但高度依賴于中心節(jié)點晃痴,一旦中心節(jié)點異常残吩,系統(tǒng)受到的影響較大;去中心化副本控制協(xié)議類似民主制度倘核,節(jié)點集體協(xié)商泣侮,效率低下,但個別節(jié)點的異常不會對系統(tǒng)總體造成太大影響紧唱。
2.3 Lease 機制
Lease 機制是最重要的分布式協(xié)議活尊,廣泛應(yīng)用于各種實際的分布式系統(tǒng)中。
基于lease 的分布式cache 系統(tǒng)
基本的問題背景如下:在一個分布式系統(tǒng)中漏益,有一個中心服務(wù)器節(jié)點蛹锰,中心服務(wù)器存儲、維護(hù)著一些數(shù)據(jù)绰疤,這些數(shù)據(jù)是系統(tǒng)的元數(shù)據(jù)铜犬。系統(tǒng)中其他的節(jié)點通過訪問中心服務(wù)器節(jié)點讀取、修改其上的元數(shù)據(jù)轻庆。由于系統(tǒng)中各種操作都依賴于元數(shù)據(jù)癣猾,如果每次讀取元數(shù)據(jù)的操作都訪問中心服務(wù)器 節(jié)點,那么中心服務(wù)器節(jié)點的性能成為系統(tǒng)的瓶頸余爆。為此纷宇,設(shè)計一種元數(shù)據(jù)cache,在各個節(jié)點上 cache 元數(shù)據(jù)信息蛾方,從而減少對中心服務(wù)器節(jié)點的訪問像捶,提高性能。另一方面转捕,系統(tǒng)的正確運行嚴(yán)格依賴于元數(shù)據(jù)的正確作岖,這就要求各個節(jié)點上cache 的數(shù)據(jù)始終與中心服務(wù)器上的數(shù)據(jù)一致,cache 中的數(shù)據(jù)不能是舊的臟數(shù)據(jù)五芝。最后痘儡,設(shè)計的cache 系統(tǒng)要能最大可能的處理節(jié)點宕機、網(wǎng)絡(luò)中斷等異常枢步,最大程度的提高系統(tǒng)的可用性沉删。
為此渐尿,利用lease 機制設(shè)計一套cache 系統(tǒng),其基本原理為如下矾瑰。中心服務(wù)器在向各節(jié)點發(fā)送數(shù)據(jù)時同時向節(jié)點頒發(fā)一個lease砖茸。每個lease 具有一個有效期,和信用卡上的有效期類似殴穴,lease 上的 有效期通常是一個明確的時間點凉夯,例如12:00:10,一旦真實時間超過這個時間點采幌,則lease 過期失效劲够。這樣lease 的有效期與節(jié)點收到lease 的時間無關(guān),節(jié)點可能收到lease 時該lease 就已經(jīng)過期失效休傍。這里首先假設(shè)中心服務(wù)器與各節(jié)點的時鐘是同步的征绎,在下節(jié)中討論時鐘不同步對lease 的影響。中心服務(wù)器發(fā)出的lease 的含義為:在lease 的有效期內(nèi)磨取,中心服務(wù)器保證不會修改對應(yīng)數(shù)據(jù)的值人柿。因此,節(jié)點收到數(shù)據(jù)和lease 后忙厌,將數(shù)據(jù)加入本地Cache凫岖,一旦對應(yīng)的lease 超時,節(jié)點將對應(yīng)的本地cache 數(shù)據(jù)刪除慰毅。中心服務(wù)器在修改數(shù)據(jù)時隘截,首先阻塞所有新的讀請求,并等待之前為該數(shù)據(jù)發(fā)出的所有l(wèi)ease 超時過期汹胃,然后修改數(shù)據(jù)的值婶芭。
基于lease 的cache,客戶端節(jié)點讀取元數(shù)據(jù)
判斷元數(shù)據(jù)是否已經(jīng)處于本地cache 且lease 處于有效期內(nèi)1.1 是:直接返回cache 中的元數(shù)據(jù)1.2 否:向中心服務(wù)器節(jié)點請求讀取元數(shù)據(jù)信息1.2.1 服務(wù)器收到讀取請求后着饥,返回元數(shù)據(jù)及一個對應(yīng)的lease 1.2.2 客戶端是否成功收到服務(wù)器返回的數(shù)據(jù) 1.2.2.1 失敗或超時:退出流程犀农,讀取失敗,可重試1.2.2.2 成功:將元數(shù)據(jù)與該元數(shù)據(jù)的lease 記錄到內(nèi)存中宰掉,返回元數(shù)據(jù)
基于lease 的cache呵哨,客戶端節(jié)點修改元數(shù)據(jù)流程2.1 節(jié)點向服務(wù)器發(fā)起修改元數(shù)據(jù)請求。2.2 服務(wù)器收到修改請求后轨奄,阻塞所有新的讀數(shù)據(jù)請求孟害,即接收讀請求,但不返回數(shù)據(jù)挪拟。2.3 服務(wù)器等待所有與該元數(shù)據(jù)相關(guān)的lease 超時挨务。2.4 服務(wù)器修改元數(shù)據(jù)并向客戶端節(jié)點返回修改成功。
上述機制可以保證各個節(jié)點上的cache 與中心服務(wù)器上的中心始終一致。這是因為中心服務(wù)器節(jié)點在發(fā)送數(shù)據(jù)的同時授予了節(jié)點對應(yīng)的lease谎柄,在lease 有效期內(nèi)丁侄,服務(wù)器不會修改數(shù)據(jù),從而客戶端節(jié)點可以放心的在lease 有效期內(nèi)cache 數(shù)據(jù)朝巫。上述lease 機制可以容錯的關(guān)鍵是:服務(wù)器一旦 發(fā)出數(shù)據(jù)及l(fā)ease鸿摇,無論客戶端是否收到,也無論后續(xù)客戶端是否宕機劈猿,也無論后續(xù)網(wǎng)絡(luò)是否正常拙吉,服務(wù)器只要等待lease 超時,就可以保證對應(yīng)的客戶端節(jié)點不會再繼續(xù)cache 數(shù)據(jù)揪荣,從而可以放心的修改數(shù)據(jù)而不會破壞cache 的一致性庐镐。
上述基礎(chǔ)流程有一些性能和可用性上的問題,但可以很容易就優(yōu)化改性变逃。優(yōu)化點一:服務(wù)器在修改元數(shù)據(jù)時首先要阻塞所有新的讀請求,造成沒有讀服務(wù)怠堪。這是為了防止發(fā)出新的lease 從而引起不斷有新客戶端節(jié)點持有l(wèi)ease 并緩存著數(shù)據(jù)揽乱,形成“活鎖”。優(yōu)化的方法很簡單粟矿,服務(wù)器在進(jìn)入修改數(shù)據(jù)流程后凰棉,一旦收到讀請求則只返回數(shù)據(jù)但不頒發(fā)lease。從而造成在修改流程執(zhí)行的過程中陌粹,客戶端可以讀到元數(shù)據(jù)撒犀,只是不能緩存元數(shù)據(jù)。進(jìn)一步的優(yōu)化是掏秩,當(dāng)進(jìn)入修改流程或舞,服務(wù)器頒發(fā)的lease 有效期限選擇為已發(fā)出的lease 的最大有效期限。這樣做蒙幻,客戶端可以繼續(xù)在服務(wù)器進(jìn)入修改流程后繼續(xù)緩存元數(shù)據(jù)映凳,但服務(wù)器的等待所有l(wèi)ease 過期的時間也不會因為頒發(fā)新的lease 而不斷延長。
最后邮破,=cache 機制與多副本機制的區(qū)別诈豌。Cache 機制與多副本機制的相似之處都 是將一份數(shù)據(jù)保存在多個節(jié)點上。但Cache 機制卻要簡單許多抒和,對于cache 的數(shù)據(jù)矫渔,可以隨時刪除丟棄,并命中cache 的后果僅僅是需要訪問數(shù)據(jù)源讀取數(shù)據(jù)摧莽;然而副本機制卻不一樣庙洼,副本是不能隨意丟棄的,每失去一個副本,服務(wù)質(zhì)量都在下降送膳,一旦副本數(shù)下降到一定程度员魏,則往往服務(wù)將不再可用。
lease 機制的分析
lease 的定義:Lease 是由頒發(fā)者授予的在某一有效期內(nèi)的承諾叠聋。頒發(fā)者一旦發(fā)出lease撕阎,則無論接受方是否收到,也無論后續(xù)接收方處于何種狀態(tài)碌补,只要lease 不過期虏束,頒發(fā)者一定嚴(yán)守承諾;另一方面厦章,接收方在lease 的有效期內(nèi)可以使用頒發(fā)者的承諾镇匀,但一旦lease 過期,接收方一定不能繼續(xù)使用頒發(fā)者的承諾袜啃。
Lease 機制具有很高的容錯能力汗侵。首先,通過引入有效期群发,Lease 機制能否非常好的容錯網(wǎng)絡(luò)異常晰韵。Lease 頒發(fā)過程只依賴于網(wǎng)絡(luò)可以單向通信,即使接收方無法向頒發(fā)者發(fā)送消息熟妓,也不影響lease 的頒發(fā)雪猪。由于lease 的有效期是一個確定的時間點,lease 的語義與發(fā)送lease 的具體時間無關(guān)起愈,所以 同一個lease 可以被頒發(fā)者不斷重復(fù)向接受方發(fā)送只恨。即使頒發(fā)者偶爾發(fā)送lease 失敗,頒發(fā)者也可以 簡單的通過重發(fā)的辦法解決抬虽。一旦lease 被接收方成功接受官觅,后續(xù)lease 機制不再依賴于網(wǎng)絡(luò)通信,即使網(wǎng)絡(luò)完全中斷l(xiāng)ease 機制也不受影響斥赋。再者缰猴,Lease 機制能較好的容錯節(jié)點宕機。如果頒發(fā)者宕機疤剑,則宕機的頒發(fā)者通常無法改變之前的承諾滑绒,不會影響lease 的正確性。在頒發(fā)者機恢復(fù)后隘膘,如果頒發(fā)者恢復(fù)出了之前的lease 信息疑故,頒發(fā)者可以繼續(xù)遵守lease 的承諾。如果頒發(fā)者無法恢復(fù)lease 信息弯菊,則只需等待一個最大的lease 超時時間就可以使得所有的lease 都失效纵势,從而不破壞lease機制。
例如上節(jié)中的cache 系統(tǒng)的例子中,一旦服務(wù)器宕機钦铁,肯定不會修改元數(shù)據(jù)软舌,重新恢復(fù)后,只需等待一個最大的lease 超時時間牛曹,所有節(jié)點上的緩存信息都將被清空佛点。對于接受方宕機的情況,頒發(fā)者 不需要做更多的容錯處理黎比,只需等待lease 過期失效超营,就可以收回承諾,實踐中也就是收回之前賦予的權(quán)限阅虫、身份等演闭。最后,lease 機制不依賴于存儲颓帝。頒發(fā)者可以持久化頒發(fā)過的lease 信息米碰,從而在 宕機恢復(fù)后可以使得在有效期的lease 繼續(xù)有效。但這對于lease 機制只是一個優(yōu)化购城,如之前的分析见间,即使頒發(fā)者沒有持久化lease 信息,也可以通過等待一個最大的lease 時間的方式使得之前所有頒發(fā) 的lease 失效工猜,從而保證機制繼續(xù)有效。
Lease 機制依賴于有效期菱蔬,這就要求頒發(fā)者和接收者的時鐘是同步的篷帅。一方面,如果頒發(fā)者的 時鐘比接收者的時鐘慢拴泌,則當(dāng)接收者認(rèn)為lease 已經(jīng)過期的時候魏身,頒發(fā)者依舊認(rèn)為lease 有效。接收者可以用在lease 到期前申請新的lease 的方式解決這個問題蚪腐。另一方面箭昵,如果頒發(fā)者的時鐘比接收 者的時鐘快,則當(dāng)頒發(fā)者認(rèn)為lease 已經(jīng)過期的時候回季,接收者依舊認(rèn)為lease 有效家制,頒發(fā)者可能將lease 頒發(fā)給其他節(jié)點,造成承諾失效泡一,影響系統(tǒng)的正確性颤殴。對于這種時鐘不同步,實踐中的通常做法是將頒發(fā)者的有效期設(shè)置得比接收者的略大鼻忠,只需大過時鐘誤差就可以避免對lease 的有效性的影響涵但。
基于lease 機制確定節(jié)點狀態(tài)
分布式協(xié)議依賴于對節(jié)點狀態(tài)認(rèn)知的全局一致性,即一旦節(jié)點Q 認(rèn)為某個節(jié)點 A 異常几苍,則節(jié)點A 也必須認(rèn)為自己異常危彩,從而節(jié)點A 停止作為primary,避免“雙主”問題的出現(xiàn)仗哨。解決這種問題有兩種思路澈侠,第一劫侧、設(shè)計的分布式協(xié)議可以容忍“雙主”錯誤,即不依賴于對節(jié)點狀 態(tài)的全局一致性認(rèn)識埋涧,或者全局一致性狀態(tài)是全體協(xié)商后的結(jié)果板辽;第二、利用lease 機制棘催。對于第一 種思路即放棄使用中心化的設(shè)計劲弦,而改用去中心化設(shè)計,超過本節(jié)的討論范疇醇坝。下面著重討論利用 lease 機制確定節(jié)點狀態(tài)邑跪。
由中心節(jié)點向其他節(jié)點發(fā)送lease,若某個節(jié)點持有有效的lease呼猪,則認(rèn)為該節(jié)點正郴可以提供服 務(wù)。用于例2.3.1 中宋距,節(jié)點A轴踱、B、C 依然周期性的發(fā)送heart beat 報告自身狀態(tài)谚赎,節(jié)點Q 收到heart beat 后發(fā)送一個lease淫僻,表示節(jié)點Q 確認(rèn)了節(jié)點A、B壶唤、C 的狀態(tài)雳灵,并允許節(jié)點在lease 有效期內(nèi)正常工 作。節(jié)點Q 可以給primary 節(jié)點一個特殊的lease闸盔,表示節(jié)點可以作為primary 工作悯辙。一旦節(jié)點Q 希望切換新的primary,則只需等前一個primary 的lease 過期迎吵,則就可以安全的頒發(fā)新的lease 給新的 primary 節(jié)點躲撰,而不會出現(xiàn)“雙主”問題。
在實際系統(tǒng)中击费,若用一個中心節(jié)點發(fā)送lease 也有很大的風(fēng)險茴肥,一旦該中心節(jié)點宕機或網(wǎng)絡(luò)異常,則所有的節(jié)點沒有l(wèi)ease荡灾,從而造成系統(tǒng)高度不可用瓤狐。為此瞬铸,實際系統(tǒng)總是使用多個中心節(jié)點互為副本,成為一個小的集群础锐,該小集群具有高可用性嗓节,對外提供頒發(fā)lease 的功能。chubby 和zookeeper 都是基于這樣的設(shè)計皆警。
lease 的有效期時間選擇
工程中拦宣,常選擇的lease 時長是10 秒級別,這是一個經(jīng)過驗證的經(jīng)驗值信姓,實踐中可以作為參考并綜合選擇合適的時長鸵隧。
2.4 Quorum 機制
先做這樣的約定:更新操作(write)是一系列順序的過程,通過其他機制確定更新操作的順序(例如primary-secondary 架構(gòu)中由primary 決定順序)意推,每個更新操作記為wi豆瘫, i 為更新操作單調(diào)遞增的序號,每個wi 執(zhí)行成功后副本數(shù)據(jù)都發(fā)生變化菊值,稱為不同的數(shù)據(jù)版本外驱,記 作vi。假設(shè)每個副本都保存了歷史上所有版本的數(shù)據(jù)腻窒。
write-all-read-one
Write-all-read-one(簡稱WARO)是一種最簡單的副本控制規(guī)則昵宇,顧名思義即在更新時寫所有的副本,只有在所有的副本上更新成功儿子,才認(rèn)為更新成功瓦哎,從而保證所有的副本一致,這樣在讀取數(shù)據(jù)時可以讀任一副本上的數(shù)據(jù)柔逼。
由于更新操作需要在所有的N 個副本上都成功杭煎,更新操作才能成 功,所以一旦有一個副本異常卒落,更新操作失敗,更新服務(wù)不可用蜂桶。對于更新服務(wù)儡毕,雖然有N 個副本, 但系統(tǒng)無法容忍任何一個副本異常扑媚。另一方面腰湾,N 個副本中只要有一個副本正常,系統(tǒng)就可以提供讀服務(wù)疆股。對于讀服務(wù)而言费坊,當(dāng)有N 個副本時,系統(tǒng)可以容忍N-1 個副本異常旬痹。從上述分析可以發(fā)現(xiàn)WARO 讀服務(wù)的可用性較高附井,但更新服務(wù)的可用性不高讨越,甚至雖然使用了副本,但更新服務(wù)的可用性等效于沒有副本永毅。
Quorum 定義
在Quorum 機制下把跨,當(dāng)某次更新操作wi 一旦在所有N 個副本中的W 個副本上都成功,則就稱 該更新操作為“成功提交的更新操作”沼死,稱對應(yīng)的數(shù)據(jù)為“成功提交的數(shù)據(jù)”着逐。令R>N-W,由于更新 操作wi 僅在W 個副本上成功意蛀,所以在讀取數(shù)據(jù)時耸别,最多需要讀取R 個副本則一定能讀到wi 更新后 的數(shù)據(jù)vi 。如果某次更新wi 在W 個副本上成功县钥,由于W+R>N秀姐,任意R 個副本組成的集合一定與 成功的W個副本組成的集合有交集,所以讀取R 個副本一定能讀到wi 更新后的數(shù)據(jù)vi魁蒜。如圖 2-10囊扳, Quorum 機制的原理可以文森圖表示。
某系統(tǒng)有5 個副本兜看,W=3锥咸,R=3,最初5 個副本的數(shù)據(jù)一致细移,都是v1搏予,某次更新操作 w2 在前3 副本上成功,副本情況變成(v2 v2 v2 v1 v1)弧轧。此時雪侥,任意3 個副本組成的集合中一定包括 v2。在上述定義中精绎,令W=N速缨,R=1,就得到WARO代乃,即WARO 是Quorum 機制的一種特例旬牲。與分析WARO 相似,分析Quorum 機制的可用性搁吓。限制Quorum 參數(shù)為W+R=N+1原茅。由于更新 操作需要在W 個副本上都成功,更新操作才能成功堕仔,所以一旦N-W+1 個副本異常擂橘,更新操作始終無法在W 個副本上成功,更新服務(wù)不可用摩骨。另一方面通贞,一旦N-R+1 個副本異常朗若,則無法保證一定可以讀到與W 個副本有交集的副本集合,則讀服務(wù)的一致性下降滑频。
再次強調(diào):僅僅依賴quorum 機制是無法保證強一致性的捡偏。因為僅有quorum 機制時無法確定最新已成功提交的版本號,除非將最新已提交的版本號作為元數(shù)據(jù)由特定的元數(shù)據(jù)服務(wù)器或元數(shù)據(jù)集群管理峡迷,否則很難確定最新成功提交的版本號银伟。在下一節(jié)中,將討論在哪些情況下绘搞,可以僅僅 通過quorum 機制來確定最新成功提交的版本號彤避。
Quorum 機制的三個系統(tǒng)參數(shù)N、W夯辖、R 控制了系統(tǒng)的可用性琉预,也是系統(tǒng)對用戶的服務(wù)承諾:數(shù)據(jù)最多有N 個副本,但數(shù)據(jù)更新成功W 個副本即返回用戶成功蒿褂。對于一致性要求較高的Quorum 系統(tǒng)圆米,系統(tǒng)還應(yīng)該承諾任何時候不讀取未成功提交的數(shù)據(jù),即讀取到的數(shù)據(jù)都是曾經(jīng)在W 個副本上成功的數(shù)據(jù)啄栓。
讀取最新成功提交的數(shù)據(jù)
Quorum 機制只需成功更新N 個副本中的W 個娄帖,在讀取R 個副本時,一定可以讀到最新的成功提交的數(shù)據(jù)昙楚。但由于有不成功的更新情況存在近速,僅僅讀取R 個副本卻不一定能確定哪個版本的數(shù)據(jù) 是最新的已提交的數(shù)據(jù)。對于一個強一致性Quorum 系統(tǒng)堪旧,若存在個數(shù)據(jù)少于W 個削葱,假設(shè)為X 個,則繼續(xù)讀取其他副本淳梦,直若成功讀取到W 個 該版本的副本析砸,則該數(shù)據(jù)為最新的成功提交的數(shù)據(jù);如果在所有副本中該數(shù)據(jù)的個數(shù)肯定不滿 足W 個爆袍,則R 中版本號第二大的為最新的成功提交的副本首繁。例:在讀取到(v2 v1 v1)時,繼續(xù)讀取剩余的副本螃宙,若讀到剩余兩個副本 為(v2 v2)則v2 是最新的已提交的副本;若讀到剩余的兩個副本為(v2 v1)或(v1 v1)則v1 是最新成功提交的版本所坯;若讀取后續(xù)兩個副本有任一超時或失敗谆扎,則無法判斷哪個版本是最新的成功提交的版本。
可以看出芹助,在單純使用Quorum 機制時堂湖,若要確定最新的成功提交的版本闲先,最多需要讀取R+ (W-R-1)=N 個副本,當(dāng)出現(xiàn)任一副本異常時无蜂,讀最新的成功提交的版本這一功能都有可能不可用伺糠。實際工程中,應(yīng)該盡量通過其他技術(shù)手段斥季,回避通過Quorum 機制讀取最新的成功提交的版本训桶。例如,當(dāng)quorum 機制與primary-secondary 控制協(xié)議結(jié)合使用時酣倾,可以通過讀取primary 的方式讀取到最新的已提交的數(shù)據(jù)舵揭。
基于Quorum 機制選擇primary副本
讀取數(shù)據(jù)時依照一致性要求的不同可以有不同的做法:如果需要強一致性的立刻讀取到最新的成功提交的數(shù)據(jù),則可以簡單的只讀取primary 副本上的數(shù)據(jù)即可躁锡,也可以通過上節(jié)的方式讀任缟;如果需要會話一致性映之,則可以根據(jù)之前已經(jīng)讀到的數(shù)據(jù)版本號在各個副本上進(jìn)行選擇性讀壤狗佟;如果只需要弱一致性杠输,則可以選擇任意副本讀取赎败。
在primary-secondary 協(xié)議中,當(dāng)primary 異常時抬伺,需要選擇出一個新的primary螟够,之后secondary 副本與primary 同步數(shù)據(jù)。通常情況下峡钓,選擇新的primary 的工作是由某一中心節(jié)點完成的妓笙,在引入 quorum 機制后,常用的primary 選擇方式與讀取數(shù)據(jù)的方式類似能岩,即中心節(jié)點讀取R 個副本寞宫,選擇 R 個副本中版本號最高的副本作為新的primary。新primary 與至少W 個副本完成數(shù)據(jù)同步后作為新的primary 提供讀寫服務(wù)拉鹃。首先辈赋,R 個副本中版本號最高的副本一定蘊含了最新的成功提交的數(shù)據(jù)。再者膏燕,雖然不能確定最高版本號的數(shù)是一個成功提交的數(shù)據(jù)钥屈,但新的primary 在隨后與secondary 同 步數(shù)據(jù),使得該版本的副本個數(shù)達(dá)到W坝辫,從而使得該版本的數(shù)據(jù)成為成功提交的數(shù)據(jù)篷就。
例:在N=5,W=3近忙,R=3 的系統(tǒng)中竭业,某時刻副本最大版本號為(v2 v2 v1 v1 v1)智润,此時v1 是系統(tǒng)的最新的成功提交的數(shù)據(jù),v2 是一個處于中間狀態(tài)的未成功提交的數(shù)據(jù)未辆。假設(shè)此刻原primary 副本異常窟绷,中心節(jié)點進(jìn)行primary 切換工作。這類“中間態(tài)”數(shù)據(jù)究竟作為“臟數(shù)據(jù)”被刪除咐柜,還是作為新的數(shù)據(jù)被同步后成為生效的數(shù)據(jù)兼蜈,完全取決于這個數(shù)據(jù)能否參與新primary 的選舉。下面分別分析這兩種情況炕桨。
第一饭尝、如圖 2-12,若中心節(jié)點與其中3 個副本通信成功献宫,讀取到的版本號為(v1 v1 v1)钥平,則任 選一個副本作為primary,新primary 以v1 作為最新的成功提交的版本并與其他副本同步姊途,當(dāng)與第1涉瘾、第2 個副本同步數(shù)據(jù)時,由于第1捷兰、第2 個副本版本號大于primary立叛,屬于臟數(shù)據(jù),可以按照2.2.2.4 節(jié)中介紹的處理臟數(shù)據(jù)的方式解決贡茅。實踐中秘蛇,新primary 也有可能與后兩個副本完成同步后就提供數(shù)據(jù)服務(wù),隨后自身版本號也更新到v2顶考,如果系統(tǒng)不能保證之后的v2 與之前的v2 完全一樣赁还,則新 primary 在與第1、2 個副本同步數(shù)據(jù)時不但要比較數(shù)據(jù)版本號還需要比較更新操作的具體內(nèi)容是否一樣驹沿。
第二艘策、若中心節(jié)點與其他3 個副本通信成功,讀取到的版本號為(v2 v1 v1)渊季,則選取版本號為 v2 的副本作為新的primary朋蔫,之后,一旦新primary 與其他2 個副本完成數(shù)據(jù)同步却汉,則符合v2 的副 本個數(shù)達(dá)到W 個驯妄,成為最新的成功提交的副本,新primary 可以提供正常的讀寫服務(wù)合砂。
2.5 日志技術(shù)
日志技術(shù)是宕機恢復(fù)的主要技術(shù)之一青扔。日志技術(shù)最初使用在數(shù)據(jù)庫系統(tǒng)中。嚴(yán)格來說日志技術(shù)不是一種分布式系統(tǒng)的技術(shù),但在分布式系統(tǒng)的實踐中赎懦,卻廣泛使用了日志技術(shù)做宕機恢復(fù),甚 至如BigTable 等系統(tǒng)將日志保存到一個分布式系統(tǒng)中進(jìn)一步增強了系統(tǒng)容錯能力幻工。
Redo Log 與Check point
設(shè)計一個高速的單機查詢系統(tǒng)存淫,將數(shù)據(jù)全部存放在內(nèi)存中以實現(xiàn)高速的數(shù)據(jù)查詢柱恤,每次更新操作更新一小部分?jǐn)?shù)據(jù)(例如 key-value 中的某一個key)。現(xiàn)在問題為利用日志技術(shù)實現(xiàn)該內(nèi)存查詢系統(tǒng)的宕機恢復(fù)。與數(shù)據(jù)庫的事務(wù)不同的是彰触,這個問題模型中的每個成功的更新操作都會生效。這也等效為數(shù)據(jù)庫的每個事務(wù)只有一個更新操作钦扭,且每次更新操作都可以也必須立即提交(Auto commit)戒劫。
-
Redo Log
將更新操作的結(jié)果(例如Set K1=1,則記錄K1=1)以追加寫(append)的方式寫入磁盤的 日志文件
按更新操作修改內(nèi)存中的數(shù)據(jù)
返回更新成功
從Redo Log 的流程可以看出胳挎,Redo 寫入日志的是更新操作完成后的結(jié)果(雖然本文不討論Undo Log饼疙,這點是與Undo Log 的區(qū)別之一),且由于是順序追加寫日志文件慕爬,在磁盤等對順序?qū)懹辛Φ?存儲設(shè)備上效率較高窑眯。
用Redo Log 進(jìn)行宕機恢復(fù)非常簡單,只需要“回放”日志即可医窿。
流程2.5.2:Redo Log 的宕機恢復(fù)
- 從頭讀取日志文件中的每次更新操作的結(jié)果磅甩,用這些結(jié)果修改內(nèi)存中的數(shù)據(jù)。
從Redo Log 的宕機恢復(fù)流程也可以看出姥卢,只有寫入日志文件的更新結(jié)果才能在宕機后恢復(fù)卷要。這也是為什么在Redo Log 流程中需要先更新日志文件再更新內(nèi)存中的數(shù)據(jù)的原因。假如先更新內(nèi)存中的數(shù)據(jù)独榴,那么用戶立刻就能讀到更新后的數(shù)據(jù)僧叉,一旦在完成內(nèi)存修改與寫入日志之間發(fā)生宕機,那么最后一次更新操作無法恢復(fù)括眠,但之前用戶可能已經(jīng)讀取到了更新后的數(shù)據(jù)彪标,從而引起不一致的問題。
-
Check point
掷豺。在簡化的模型下捞烟,check point 技術(shù)的過程即將內(nèi)存中的數(shù)據(jù)以某種易于重新加載的數(shù)據(jù)組織方式完整的dump 到磁盤,從而減少宕機恢復(fù)時需要回放的日志數(shù)據(jù)当船。
流程:check point
向日志文件中記錄“Begin Check Point”
將內(nèi)存中的數(shù)據(jù)以某種易于重新加載的數(shù)據(jù)組織方式dump 到磁盤上
向日志文件中記錄“End Check Point” 在check point 流程中题画,數(shù)據(jù)可以繼續(xù)按照流程2.5.1 被更新,這段過程中新更新的數(shù)據(jù)可以dump 到磁盤也可以不dump 到磁盤德频,具體取決于實現(xiàn)苍息。例如,check point 開始時k1=v1,check point 過程 中某次更新為k1 = v2竞思,那么dump 到磁盤上的k1 的值可以是v1 也可以是v2表谊。
流程:基于check point 的宕機恢復(fù)流程
將dump 到磁盤的數(shù)據(jù)加載到內(nèi)存。
從后向前掃描日志文件盖喷,尋找最后一個“End Check Point”日志爆办。
從最后一個“End Check Point”日志向前找到最近的一個“Begin Check Point”日志,并回 放該日志之后的所有更新操作日志课梳。
-
No Undo/No Redo log
若數(shù)據(jù)維護(hù)在磁盤中距辆,某批更新由若干個更新操作組成,這些更新操作需要原子生效暮刃,即要么同時生效跨算,要么都不生效。
0/1 目錄技術(shù)中有兩個目錄結(jié)構(gòu)椭懊,稱為目錄0(Directory 0)和目錄1(Directory 1)诸蚕。另有一個結(jié)構(gòu)稱為主記錄(Master record)記錄當(dāng)前正在使用的目錄稱為活動目錄。主記錄中要么記錄使用目錄0氧猬,要么記錄使用目錄1挫望。目錄0 或目錄1 中記錄了各個數(shù)據(jù)的在日志文件中的位置。0/1 目錄的數(shù)據(jù)更新過程始終在非活動目錄上進(jìn)行狂窑,只是在數(shù)據(jù)生效前媳板,將主記錄中的0、1 值反轉(zhuǎn)泉哈,從而切換主記錄蛉幸。
流程:0/1 目錄數(shù)據(jù)更新流程
將活動目錄完整拷貝到非活動目錄。
對于每個更新操作丛晦,新建一個日志項紀(jì)錄操作后的值奕纫,并在非活動目錄中將相應(yīng)數(shù)據(jù)的位置修改為新建的日志項的位置。
原子性修改主記錄:反轉(zhuǎn)主記錄中的值烫沙,使得非活動目錄生效匹层。
0/1 目錄的更新流程非常簡單,通過0锌蓄、1 目錄的主記錄切換使得一批修改的生效是原子的升筏。0/1 目錄將批量事務(wù)操作的原子性通過目錄手段歸結(jié)到主記錄的原子切換。由于多條記錄的原子修改一般較難實現(xiàn)而單條記錄的原子修改往往可以實現(xiàn)瘸爽,從而降低了問題實現(xiàn)的難度您访。在工程中0/1 目錄的思想運用非常廣泛,其形式也不局限在上述流程中剪决,可以是內(nèi)存中的兩個數(shù)據(jù)結(jié)構(gòu)來回切換灵汪,也可以是磁盤上的兩個文件目錄來回生效切換檀训。
2.6 兩階段提交協(xié)議
兩階段提交協(xié)議是一種經(jīng)典的強一致性中心化副本控制協(xié)議。雖然在工程中該協(xié)議有較多的問題享言,但研究該協(xié)議能很好的理解分布式系統(tǒng)的幾個典型問題峻凫。
流程描述
兩階段提交協(xié)議是一種典型的“中心化副本控制”協(xié)議。在該協(xié)議中览露,參與的節(jié)點分為兩類:一個中心化協(xié)調(diào)者節(jié)點(coordinator)和N 個參與者節(jié)點(participant)蔚晨。每個參與者節(jié)點即上文背景介紹中的管理數(shù)據(jù)庫副本的節(jié)點。
兩階段提交的思路比較簡單肛循,在第一階段,協(xié)調(diào)者詢問所有的參與者是否可以提交事務(wù)(請參與者投票)银择,所有參與者向協(xié)調(diào)者投票多糠。在第二階段,協(xié)調(diào)者根據(jù)所有參與者的投票結(jié)果做出是否事務(wù)可以全局提交的決定浩考,并通知所有的參與者執(zhí)行該決定夹孔。在一個兩階段提交流程中,參與者不能改變自己的投票結(jié)果析孽。兩階段提交協(xié)議的可以全局提交的前提是所有的參與者都同意提交事務(wù)搭伤,只要有一個參與者投票選擇放棄(abort)事務(wù),則事務(wù)必須被放棄袜瞬。
流程:兩階段提交協(xié)調(diào)者流程
寫本地日志“begin_commit”怜俐,并進(jìn)入WAIT 狀態(tài);
向所有參與者發(fā)送“prepare 消息”邓尤;
等待并接收參與者發(fā)送的對“prepare 消息”的響應(yīng)拍鲤;3.1 若收到任何一個參與者發(fā)送的“vote-abort 消息”;3.1.1 寫本地“global-abort”日志汞扎,進(jìn)入ABORT季稳;3.1.2 向所有的參與者發(fā)送“global-abort 消息”;3.1.3 進(jìn)入ABORT 狀態(tài)澈魄;3.2 若收到所有參與者發(fā)送的“vote-commit”消息景鼠;3.2.1 寫本地“global-commit”日志,進(jìn)入COMMIT 狀態(tài)痹扇;3.1.2 向所有的參與者發(fā)送“global-commit 消息”铛漓;
等待并接收參與者發(fā)送的對“global-abort 消息”或“global-commit 消息”的確認(rèn)響應(yīng)消息,一旦收到所有參與者的確認(rèn)消息鲫构,寫本地“end_transaction” 日志流程結(jié)束票渠。
流程:兩階段提交協(xié)調(diào)者流程
寫本地日志“init”記錄,進(jìn)入INIT 狀態(tài)
等待并接受協(xié)調(diào)者發(fā)送的“prepare 消息”芬迄,收到后 2.1 若參與者可以提交本次事務(wù) 2.1.1 寫本地日志“ready”问顷,進(jìn)入READY 狀態(tài) 2.1.2 向協(xié)調(diào)者發(fā)送“vote-commit”消息 2.1.4 等待協(xié)調(diào)者的消息2.1.4.1 若收到協(xié)調(diào)者的“global-abort”消息2.1.4.1.1 寫本地日志“abort”,進(jìn)入ABORT 狀態(tài)2.1.4.1.2 向協(xié)調(diào)者發(fā)送對“global-abort”的確認(rèn)消息 2.1.4.2 若收到協(xié)調(diào)者的“global-commit”消息2.1.4.1.1 寫本地日志“commit”,進(jìn)入COMMIT 狀態(tài) 2.1.4.1.2 向協(xié)調(diào)者發(fā)送對“global-commit”的確認(rèn)消息 2.2 若參與者無法提交本次事務(wù) 2.2.1 寫本地日志“abort”杜窄,進(jìn)入ABORT 狀態(tài) 2.2.2 向協(xié)調(diào)者發(fā)送“vote-abort”消息 2.2.3 流程對該參與者結(jié)束 2.2.4 若后續(xù)收到協(xié)調(diào)者的“global-abort”消息可以響應(yīng)
即使流程結(jié)束肠骆,但任何時候收到協(xié)調(diào)者發(fā)送的“global-abort”消息或“global-commit”消息也都要發(fā)送一個對應(yīng)的確認(rèn)消息。
異常處理
宕機恢復(fù)
協(xié)調(diào)者宕機恢復(fù) 協(xié)調(diào)者宕機恢復(fù)后塞耕,首先通過日志查找到宕機前的狀態(tài)蚀腿。如果日志中最后是“begin_commit”記錄,說明宕機前協(xié)調(diào)者處于WAIT 狀態(tài)扫外,協(xié)調(diào)者可能已經(jīng)發(fā)送過“prepare 消息”也可能還沒發(fā)送莉钙,但協(xié)調(diào)者一定還沒有發(fā)送過“global-commit 消息”或“global-abort 消息”,即事務(wù)的全局狀態(tài)還沒有確定筛谚。此時磁玉,協(xié)調(diào)者可以重新發(fā)送“prepare 消息” 繼續(xù)兩階段提交流程,即使參與者已經(jīng)發(fā)送過對“prepare 消息”的響應(yīng)驾讲,也不過是再次重傳之前的響應(yīng)而不會影響協(xié)議的一致性蚊伞。如果日志中最后是“global-commit”或“global-abort”記錄,說明宕機前協(xié)調(diào)者處于COMMIT 或ABORT 狀態(tài)吮铭。此時協(xié)調(diào)者只需重新向所有的參與者發(fā)送“global-commit 消息”或“global-abort 消息”就可以繼續(xù)兩階段提交流程时迫。
參與者宕機恢復(fù)參與者宕機恢復(fù)后,首先通過日志查找宕機前的狀態(tài)谓晌。如果日志中最后是“init”記錄掠拳,說明參與者處于INIT 狀態(tài),還沒有對本次事務(wù)做出投票選擇纸肉,參與者可以繼續(xù)流程等待協(xié)調(diào)者發(fā)送的“prepare 消息”碳想。如果日志中最后是“ready”記錄,說明參與者處于REDAY 狀態(tài)毁靶,此時說明參與者已經(jīng)就本次 事務(wù)做出了投票選擇胧奔,但宕機前參與者是否已經(jīng)向協(xié)調(diào)者發(fā)送“vote-commit”消息并不可知。所以此時參與者可以向協(xié)調(diào)者重發(fā)“vote-commit”预吆,并繼續(xù)協(xié)議流程龙填。如果日志中最后是“commit”或“abort”記錄,說明參與者已經(jīng)收到過協(xié)調(diào)者的“global-commit 消息”(處于COMMIT 狀態(tài))或者“global-abort 消息”(處于ABORT 狀態(tài))拐叉。至于是否向協(xié)調(diào)者發(fā) 送過對“global-commit”或“global-abort”的確認(rèn)消息則未知岩遗。但即使沒有發(fā)送過確認(rèn)消息,由于協(xié)調(diào)者會不斷重發(fā)“global-commit”或“global-abort”凤瘦,只需在收到這些消息時發(fā)送確認(rèn)消息既可宿礁,不影響協(xié)議的全局一致性。
協(xié)議分析
兩階段提交協(xié)議在工程實踐中真正使用的較少蔬芥,主要原因有以下幾點:
兩階段提交協(xié)議的容錯能力較差梆靖。從上文的分析可以看出控汉,兩階段提交協(xié)議在某些情況下存在流程無法執(zhí)行下去的情況,且也無法判斷流程狀態(tài)返吻。在工程中好的分布式協(xié)議往往總是可以在即使發(fā)生異常的情況下也能執(zhí)行下去姑子。例如,回憶Lease 機制(2.3 )测僵,一旦lease 發(fā)出街佑,無論出現(xiàn)任何異常,Lease 服務(wù)器節(jié)點總是可以通過時間判定出Lease 是否有效捍靠,也可以用等待Lease 超時的方法收回Lease 權(quán)限沐旨,整個Lease 協(xié)議的流程不存在任何流程被阻塞而無法執(zhí)行下去的情況。與Lease 機制的簡單有效相比榨婆,兩階段提交的協(xié)議顯得較為復(fù)雜且容錯能力差磁携。
兩階段提交協(xié)議的性能較差。一次成功的兩階段提交協(xié)議流程中纲辽,協(xié)調(diào)者與每個參與者 之間至少需要兩輪交互4 個消息“prepare”、“vote-commit”璃搜、“global-commit”拖吼、“確認(rèn)global-commit”。過多的交互次數(shù)會降低性能这吻。另一方面吊档,協(xié)調(diào)者需要等待所有的參與者的投票結(jié)果,一旦存在較慢的參與者唾糯,會影響全局流程執(zhí)行速度怠硼。
雖然存在一些改進(jìn)的兩階段提交協(xié)議可以提高容錯能力和性能,然而這類協(xié)議依舊是在工程中使用較少的一類協(xié)議移怯,其理論價值大于實踐意義香璃。
2.7 MVCC
MVCC(Multi-version Cocurrent Control,多版本并發(fā)控制)技術(shù)舟误。MVCC 技術(shù)最初也是在數(shù)據(jù)庫系統(tǒng)中被提出葡秒,但這種思想并不局限于單機的分布式系統(tǒng),在分布式系統(tǒng)中同樣有效嵌溢。
MVCC 即多個不同版本的數(shù)據(jù)實現(xiàn)并發(fā)控制的技術(shù)眯牧,其基本思想是為每次事務(wù)生成 一個新版本的數(shù)據(jù),在讀數(shù)據(jù)時選擇不同版本的數(shù)據(jù)即可以實現(xiàn)對事務(wù)結(jié)果的完整性讀取赖草。在使用MVCC 時学少,每個事務(wù)都是基于一個已生效的基礎(chǔ)版本進(jìn)行更新,事務(wù)可以并行進(jìn)行秧骑,從而可以產(chǎn)生一種圖狀結(jié)構(gòu)版确。基礎(chǔ)數(shù)據(jù)的版本為1扣囊,同時產(chǎn)生了兩個事務(wù):事務(wù)A 與事務(wù)B。這兩個事務(wù)都各自對數(shù)據(jù)進(jìn)行了一些本地修改(這些修改只有事務(wù)自己可見阀坏,不影響真正的數(shù)據(jù))如暖,之后事務(wù)A 首先提交,生成數(shù)據(jù)版本2忌堂;基于數(shù)據(jù)版本2盒至,又發(fā)起了事務(wù)C,事務(wù)C 繼續(xù)提交士修,生成了數(shù)據(jù)版 本3枷遂;最后事務(wù)B 提交,此時事務(wù)B 的結(jié)果需要與事務(wù)C 的結(jié)果合并棋嘲,如果數(shù)據(jù)沒有沖突酒唉,即事務(wù) B 沒有修改事務(wù)A 與事務(wù)C 修改過的變量,那么事務(wù)B 可以提交沸移,否則事務(wù)B 提交失敗痪伦。MVCC 的流程過程非常類似于SVN 等版本控制系統(tǒng)的流程,或者說SVN 等版本控制系統(tǒng)就是 使用的MVCC 思想雹锣。事務(wù)在基于基礎(chǔ)數(shù)據(jù)版本做本地修改時网沾,為了不影響真正的數(shù)據(jù),通常有兩種做法蕊爵,一是將基礎(chǔ)數(shù)據(jù)版本中的數(shù)據(jù)完全拷貝出來再修改辉哥,SVN 即使用了這種方法,SVN check out 即是拷貝的過程攒射;二是每個事務(wù)中只記錄更新操作醋旦,而不記錄完整的數(shù)據(jù),讀取數(shù)據(jù)時再將更新操作應(yīng)用到用基礎(chǔ)版本的數(shù)據(jù)從而計算出結(jié)果会放,這個過程也類似SVN 的增量提交饲齐。
2.8 Paxos協(xié)議
Paxos 協(xié)議是少數(shù)在工程實踐中證實的強一致性、高可用的去中心化分布式協(xié)議咧最。Paxos 協(xié)議的流程較為復(fù)雜箩张,但其基本思想?yún)s不難理解,類似于人類社會的投票過程窗市。Paxos 協(xié)議中先慷,有一組完全對等的參與節(jié)點(稱為accpetor),這組節(jié)點各自就某一事件做出決議咨察,如果某個決議獲得了超過半數(shù)節(jié)點的同意則生效论熙。Paxos 協(xié)議中只要有超過一半的節(jié)點正常,就可以工作摄狱,能很好對抗宕機脓诡、網(wǎng)絡(luò)分化等異常情況无午。
角色
Proposer:提案者。Proposer 可以有多個祝谚,Proposer 提出議案(value)宪迟。所謂value,在工程中可以是任何操作交惯,例如“修改某個變量的值為某個值”次泽、“設(shè)置當(dāng)前primary 為某個節(jié)點”等等。Paxos 協(xié)議中統(tǒng)一將這些操作抽象為value席爽。不同的Proposer 可以提出不同的甚至矛盾的value意荤,例如某個Proposer 提議“將變量X 設(shè)置為1”,另一個Proposer 提議“將變量X 設(shè)置為2”只锻,但對同一輪Paxos 過程玖像,最多只有一個value 被批準(zhǔn)。Acceptor:批準(zhǔn)者齐饮。Acceptor 有N 個捐寥,Proposer 提出的value 必須獲得超過半數(shù)(N/2+1)的Acceptor 批準(zhǔn)后才能通過。Acceptor 之間完全對等獨立祖驱。Learner:學(xué)習(xí)者握恳。Learner 學(xué)習(xí)被批準(zhǔn)的value。所謂學(xué)習(xí)就是通過讀取各個Proposer 對value 的選擇結(jié)果羹膳,如果某個value 被超過半數(shù)Proposer 通過睡互,則Learner 學(xué)習(xí)到了這個value根竿×晗瘢回憶(2.4 ) 不難理解,這里類似Quorum 機制寇壳,某個value 需要獲得W=N/2 + 1 的Acceptor 批準(zhǔn)醒颖,從而學(xué)習(xí)者需要至少讀取N/2+1 個Accpetor,至多讀取N 個Acceptor 的結(jié)果后壳炎,能學(xué)習(xí)到一個通過的value泞歉。上述三類角色只是邏輯上的劃分,實踐中一個節(jié)點可以同時充當(dāng)這三類角色匿辩。
流程
Paxos 協(xié)議一輪一輪的進(jìn)行腰耙,每輪都有一個編號。每輪Paxos 協(xié)議可能會批準(zhǔn)一個value铲球,也可 能無法批準(zhǔn)一個value挺庞。如果某一輪Paxos 協(xié)議批準(zhǔn)了某個value,則以后各輪Paxos 只能批準(zhǔn)這個 value稼病。上述各輪協(xié)議流程組成了一個Paxos 協(xié)議實例选侨,即一次Paxos 協(xié)議實例只能批準(zhǔn)一個value掖鱼,這也是Paxos 協(xié)議強一致性的重要體現(xiàn)。每輪Paxos 協(xié)議分為階段援制,準(zhǔn)備階段和批準(zhǔn)階段戏挡,在這兩個階段Proposer 和Acceptor 有各自的處理流程。
流程:Proposer 的流程 (準(zhǔn)備階段)
向所有的Acceptor 發(fā)送消息“Prepare(b)”晨仑;這里b 是Paxos 的輪數(shù)褐墅,每輪遞增
如果收到任何一個Acceptor 發(fā)送的消息“Reject(B)”,則對于這個Proposer 而言本輪Paxos 失敗寻歧,將輪數(shù)b 設(shè)置為B+1 后重新步驟1掌栅;(批準(zhǔn)階段,根據(jù)收到的Acceptor 的消息作出不同選擇)
如果接收到的Acceptor 的“Promise(b, v_i)”消息達(dá)到N/2+1 個(N 為Acceptor 總數(shù)码泛,除法取整猾封, 下同);v_i 表示Acceptor 最近一次在i 輪批準(zhǔn)過value v噪珊。3.1 如果收到的“Promise(b, v)”消息中晌缘,v 都為空,Proposer 選擇一個value v痢站,向所有Acceptor 廣播Accept(b, v)磷箕;3.2 否則,在所有收到的“Promise(b, v_i)”消息中阵难,選擇i 最大的value v岳枷,向所有Acceptor 廣播消息Accept(b,v)呜叫;
如果收到Nack(B)空繁,將輪數(shù)b 設(shè)置為B+1 后重新步驟1;
流程:Accpetor 流程 (準(zhǔn)備階段)
接受某個Propeser 的消息Prepare(b)朱庆。參數(shù)B 是該Acceptor 收到的最大Paxos 輪數(shù)編號盛泡;V 是Acceptor 批準(zhǔn)的value,可以為空 1.1 如果b>B娱颊,回復(fù)Promise(b, V_B)傲诵,設(shè)置B=b; 表示保證不再接受編號小于b 的提案。1.2 否則箱硕,回復(fù)Reject(B) (批準(zhǔn)階段)
接收Accept(b, v)拴竹, 2.1 如果b < B, 回復(fù)Nack(B)号醉,暗示proposer 有一個更大編號的提案被這個Acceptor 接收了 2.2 否則設(shè)置V=v惨篱。表示這個Acceptor 批準(zhǔn)的Value 是v。廣播Accepted 消息叫胁。
例子
基本例子里有5 個Acceptor,1 個Proposer菱属,不存在任何網(wǎng)絡(luò)钳榨、宕機異常。我們著重考察各個Accpetor 上變量B 和變量V 的變化纽门,及Proposer 上變量b 的變化薛耻。
-
初始狀態(tài)image
-
Proposer 向所有Accpetor 發(fā)送“Prepare(1)”,所有Acceptor 正確處理赏陵,并回復(fù)Promise(1, NULLimage
-
Proposer 收到5 個Promise(1, NULL)饼齿,滿足多余半數(shù)的Promise 的value 為空,此時發(fā)送 Accept(1, v1)蝙搔,其中v1 是Proposer 選擇的Value缕溉。image
此時,v1 被超過半數(shù)的Acceptor 批準(zhǔn)吃型,v1 即是本次Paxos 協(xié)議實例批準(zhǔn)的Value证鸥。如果Learner 學(xué)習(xí)value,學(xué)到的只能是v1
在同一個Paxos 實例中勤晚,批準(zhǔn)的Value 是無法改變的枉层,即使后續(xù)Proposer 以更高的序號發(fā)起Paxos 協(xié)議也無法改變value。Paxos 協(xié)議的核心就在于“批準(zhǔn)的value 無法改變”赐写,這也是整個協(xié)議正確性的基礎(chǔ)鸟蜡。
Paxos 協(xié)議是被人為設(shè)計出來,其設(shè)計過程也是協(xié)議的推導(dǎo)過程挺邀。Paxos 協(xié)議利用了Quorom 機 制揉忘,選擇的W=R=N/2+1。簡單而言端铛,協(xié)議就是Proposer 更新Acceptor 的過程泣矛,一旦某個Acceptor 成功更新了超過半數(shù)的Acceptor,則更新成功沦补。Learner 按Quorum 去讀取Acceptor乳蓄,一旦某個value 在超過半數(shù)的Proposer 上被成功讀取咪橙,則說明這是一個被批準(zhǔn)的value夕膀。協(xié)議通過引入輪次,使得高輪次的提議搶占低輪次的提議來避免死鎖美侦。協(xié)議設(shè)計關(guān)鍵點是如何滿足“在一次Paxos 算法實例過程中只批準(zhǔn)一個Value”這一約束條件产舞。
2.9 CAP
CAP 理論的定義很簡單,CAP 三個字母分別代表了分布式系統(tǒng)中三個相互矛盾的屬性:
Consistency (一致性):CAP 理論中的副本一致性特指強一致性(1.3.4 )菠剩;
Availiablity(可用性):指系統(tǒng)在出現(xiàn)異常時已經(jīng)可以提供服務(wù)易猫;
Tolerance to the partition of network (分區(qū)容忍):指系統(tǒng)可以對網(wǎng)絡(luò)分區(qū)(1.1.4.2 )這種異常情 況進(jìn)行容錯處理;
CAP 理論指出:無法設(shè)計一種分布式協(xié)議具壮,使得同時完全具備CAP 三個屬性准颓,即1)該種協(xié)議下的副本始終是強一致性哈蝇,2)服務(wù)始終是可用的,3)協(xié)議可以容忍任何網(wǎng)絡(luò)分區(qū)異常攘已;分布式系統(tǒng)協(xié)議只能在CAP 這三者間所有折中炮赦。
熱力學(xué)第二定律說明了永動機是不可能存在的,不要去妄圖設(shè)計永動機样勃。與之類似吠勘,CAP 理論的意義就在于明確提出了不要去妄圖設(shè)計一種對CAP 三大屬性都完全擁有的完美系統(tǒng),因為這種系統(tǒng)在理論上就已經(jīng)被證明不存在峡眶。
Lease 機制: Lease 機制犧牲了部分異常情況下的A剧防,從而獲得了完全的C 與很好的P。
Quorum 機制: Quorum 機制辫樱,在CAP 三大因素中都各做了折中峭拘,有一定的C,有較好 的A狮暑,也有較好的P棚唆,是一種較為平衡的分布式協(xié)議。
兩階段提交協(xié)議: 兩階段提交系統(tǒng)具有完全的C心例,很糟糕的A宵凌,很糟糕的P。
Paxos 協(xié)議:同樣是強一致性協(xié)議止后,Paxos 在CAP 三方面較之兩階段提交協(xié)議要優(yōu)秀得多瞎惫。Paxos 協(xié)議具有 完全的C,較好的A译株,較好的P瓜喇。Paxos 的A 與P 的屬性與Quorum 機制類似,因為Paxos 的協(xié)議本 身就具有Quorum 機制的因素歉糜。