最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

萬(wàn)字長(zhǎng)文-詳解分布式算法

2023-10-22 21:54 作者:程序員升職加薪  | 我要投稿


好死還是賴(lài)活著? —— Jay Kreps, 關(guān)于 Kafka 與 Jepsen 的若干筆記 (2013)


先緩解下疲勞、兄弟們、下面的內(nèi)容比較費(fèi)腦子、先清醒一波、手動(dòng)狗頭!



正如 第八章 所討論的,分布式系統(tǒng)中的許多事情可能會(huì)出錯(cuò)。處理這種故障的最簡(jiǎn)單方法是簡(jiǎn)單地讓整個(gè)服務(wù)失效,并向用戶(hù)顯示錯(cuò)誤消息。如果無(wú)法接受這個(gè)解決方案,我們就需要找到容錯(cuò)的方法 —— 即使某些內(nèi)部組件出現(xiàn)故障,服務(wù)也能正常運(yùn)行。

在本章中,我們將討論構(gòu)建容錯(cuò)分布式系統(tǒng)的算法和協(xié)議的一些例子。我們將假設(shè) 第八章 的所有問(wèn)題都可能發(fā)生:網(wǎng)絡(luò)中的數(shù)據(jù)包可能會(huì)丟失、重新排序、重復(fù)推送或任意延遲;時(shí)鐘只是盡其所能地近似;且節(jié)點(diǎn)可以暫停(例如,由于垃圾收集)或隨時(shí)崩潰。

構(gòu)建容錯(cuò)系統(tǒng)的最好方法,是找到一些帶有實(shí)用保證的通用抽象,實(shí)現(xiàn)一次,然后讓?xiě)?yīng)用依賴(lài)這些保證。這與 第七章 中的事務(wù)處理方法相同:通過(guò)使用事務(wù),應(yīng)用可以假裝沒(méi)有崩潰(原子性),沒(méi)有其他人同時(shí)訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)(隔離),存儲(chǔ)設(shè)備是完全可靠的(持久性)。即使發(fā)生崩潰,競(jìng)態(tài)條件和磁盤(pán)故障,事務(wù)抽象隱藏了這些問(wèn)題,因此應(yīng)用不必?fù)?dān)心它們。

現(xiàn)在我們將繼續(xù)沿著同樣的路線(xiàn)前進(jìn),尋求可以讓?xiě)?yīng)用忽略分布式系統(tǒng)部分問(wèn)題的抽象概念。例如,分布式系統(tǒng)最重要的抽象之一就是 共識(shí)(consensus)就是讓所有的節(jié)點(diǎn)對(duì)某件事達(dá)成一致。正如我們?cè)诒菊轮袑?huì)看到的那樣,要可靠地達(dá)成共識(shí),且不被網(wǎng)絡(luò)故障和進(jìn)程故障所影響,是一個(gè)令人驚訝的棘手問(wèn)題。

一旦達(dá)成共識(shí),應(yīng)用可以將其用于各種目的。例如,假設(shè)你有一個(gè)單主復(fù)制的數(shù)據(jù)庫(kù)。如果主庫(kù)掛掉,并且需要故障切換到另一個(gè)節(jié)點(diǎn),剩余的數(shù)據(jù)庫(kù)節(jié)點(diǎn)可以使用共識(shí)來(lái)選舉新的領(lǐng)導(dǎo)者。正如在 “處理節(jié)點(diǎn)宕機(jī)” 中所討論的那樣,重要的是只有一個(gè)領(lǐng)導(dǎo)者,且所有的節(jié)點(diǎn)都認(rèn)同其領(lǐng)導(dǎo)。如果兩個(gè)節(jié)點(diǎn)都認(rèn)為自己是領(lǐng)導(dǎo)者,這種情況被稱(chēng)為 腦裂(split brain),它經(jīng)常會(huì)導(dǎo)致數(shù)據(jù)丟失。正確實(shí)現(xiàn)共識(shí)有助于避免這種問(wèn)題。

在本章后面的 “分布式事務(wù)與共識(shí)” 中,我們將研究解決共識(shí)和相關(guān)問(wèn)題的算法。但首先,我們首先需要探索可以在分布式系統(tǒng)中提供的保證和抽象的范圍。

我們需要了解可以做什么和不可以做什么的范圍:在某些情況下,系統(tǒng)可以容忍故障并繼續(xù)工作;在其他情況下,這是不可能的。我們將深入研究什么可能而什么不可能的限制,既通過(guò)理論證明,也通過(guò)實(shí)際實(shí)現(xiàn)。我們將在本章中概述這些基本限制。

分布式系統(tǒng)領(lǐng)域的研究人員幾十年來(lái)一直在研究這些主題,所以有很多資料 —— 我們只能介紹一些皮毛。在本書(shū)中,我們沒(méi)有空間去詳細(xì)介紹形式模型和證明的細(xì)節(jié),所以我們會(huì)按照直覺(jué)來(lái)介紹。如果你有興趣,參考文獻(xiàn)可以提供更多的深度。

一致性保證

在 “復(fù)制延遲問(wèn)題” 中,我們看到了數(shù)據(jù)庫(kù)復(fù)制中發(fā)生的一些時(shí)序問(wèn)題。如果你在同一時(shí)刻查看兩個(gè)數(shù)據(jù)庫(kù)節(jié)點(diǎn),則可能在兩個(gè)節(jié)點(diǎn)上看到不同的數(shù)據(jù),因?yàn)閷?xiě)請(qǐng)求在不同的時(shí)間到達(dá)不同的節(jié)點(diǎn)。無(wú)論數(shù)據(jù)庫(kù)使用何種復(fù)制方法(單主復(fù)制,多主復(fù)制或無(wú)主復(fù)制),都會(huì)出現(xiàn)這些不一致情況。

大多數(shù)復(fù)制的數(shù)據(jù)庫(kù)至少提供了 最終一致性,這意味著如果你停止向數(shù)據(jù)庫(kù)寫(xiě)入數(shù)據(jù)并等待一段不確定的時(shí)間,那么最終所有的讀取請(qǐng)求都會(huì)返回相同的值【1】。換句話(huà)說(shuō),不一致性是暫時(shí)的,最終會(huì)自行解決(假設(shè)網(wǎng)絡(luò)中的任何故障最終都會(huì)被修復(fù))。最終一致性的一個(gè)更好的名字可能是 收斂(convergence),因?yàn)槲覀冾A(yù)計(jì)所有的副本最終會(huì)收斂到相同的值【2】。

然而,這是一個(gè)非常弱的保證 —— 它并沒(méi)有說(shuō)什么時(shí)候副本會(huì)收斂。在收斂之前,讀操作可能會(huì)返回任何東西或什么都沒(méi)有【1】。例如,如果你寫(xiě)入了一個(gè)值,然后立即再次讀取,這并不能保證你能看到剛才寫(xiě)入的值,因?yàn)樽x請(qǐng)求可能會(huì)被路由到另外的副本上。(請(qǐng)參閱 “讀己之寫(xiě)” )。

對(duì)于應(yīng)用開(kāi)發(fā)人員而言,最終一致性是很困難的,因?yàn)樗c普通單線(xiàn)程程序中變量的行為有很大區(qū)別。對(duì)于后者,如果將一個(gè)值賦給一個(gè)變量,然后很快地再次讀取,不可能讀到舊的值,或者讀取失敗。數(shù)據(jù)庫(kù)表面上看起來(lái)像一個(gè)你可以讀寫(xiě)的變量,但實(shí)際上它有更復(fù)雜的語(yǔ)義【3】。

在與只提供弱保證的數(shù)據(jù)庫(kù)打交道時(shí),你需要始終意識(shí)到它的局限性,而不是意外地作出太多假設(shè)。錯(cuò)誤往往是微妙的,很難找到,也很難測(cè)試,因?yàn)閼?yīng)用可能在大多數(shù)情況下運(yùn)行良好。當(dāng)系統(tǒng)出現(xiàn)故障(例如網(wǎng)絡(luò)中斷)或高并發(fā)時(shí),最終一致性的邊緣情況才會(huì)顯現(xiàn)出來(lái)。

本章將探索數(shù)據(jù)系統(tǒng)可能選擇提供的更強(qiáng)一致性模型。它不是免費(fèi)的:具有較強(qiáng)保證的系統(tǒng)可能會(huì)比保證較差的系統(tǒng)具有更差的性能或更少的容錯(cuò)性。盡管如此,更強(qiáng)的保證能夠吸引人,因?yàn)樗鼈兏菀子脤?duì)。只有見(jiàn)過(guò)不同的一致性模型后,才能更好地決定哪一個(gè)最適合自己的需求。

分布式一致性模型 和我們之前討論的事務(wù)隔離級(jí)別的層次結(jié)構(gòu)有一些相似之處【4,5】(請(qǐng)參閱 “弱隔離級(jí)別”)。盡管兩者有一部分內(nèi)容重疊,但它們大多是無(wú)關(guān)的問(wèn)題:事務(wù)隔離主要是為了 避免由于同時(shí)執(zhí)行事務(wù)而導(dǎo)致的競(jìng)爭(zhēng)狀態(tài),而分布式一致性主要關(guān)于 在面對(duì)延遲和故障時(shí)如何協(xié)調(diào)副本間的狀態(tài)

本章涵蓋了廣泛的話(huà)題,但我們將會(huì)看到這些領(lǐng)域?qū)嶋H上是緊密聯(lián)系在一起的:

  • 首先看一下常用的 最強(qiáng)一致性模型 之一,線(xiàn)性一致性(linearizability),并考察其優(yōu)缺點(diǎn)。

  • 然后我們將檢查分布式系統(tǒng)中 事件順序 的問(wèn)題,特別是因果關(guān)系和全局順序的問(wèn)題。

  • 在第三節(jié)的(“分布式事務(wù)與共識(shí)”)中將探討如何原子地提交分布式事務(wù),這將最終引領(lǐng)我們走向共識(shí)問(wèn)題的解決方案。

線(xiàn)性一致性

最終一致 的數(shù)據(jù)庫(kù),如果你在同一時(shí)刻問(wèn)兩個(gè)不同副本相同的問(wèn)題,可能會(huì)得到兩個(gè)不同的答案。這很讓人困惑。如果數(shù)據(jù)庫(kù)可以提供只有一個(gè)副本的假象(即,只有一個(gè)數(shù)據(jù)副本),那么事情就簡(jiǎn)單太多了。那么每個(gè)客戶(hù)端都會(huì)有相同的數(shù)據(jù)視圖,且不必?fù)?dān)心復(fù)制滯后了。

這就是 線(xiàn)性一致性(linearizability) 背后的想法【6】(也稱(chēng)為 原子一致性(atomic consistency)【7】,強(qiáng)一致性(strong consistency),立即一致性(immediate consistency)外部一致性(external consistency )【8】)。線(xiàn)性一致性的精確定義相當(dāng)微妙,我們將在本節(jié)的剩余部分探討它。但是基本的想法是讓一個(gè)系統(tǒng)看起來(lái)好像只有一個(gè)數(shù)據(jù)副本,而且所有的操作都是原子性的。有了這個(gè)保證,即使實(shí)際中可能有多個(gè)副本,應(yīng)用也不需要擔(dān)心它們。

在一個(gè)線(xiàn)性一致的系統(tǒng)中,只要一個(gè)客戶(hù)端成功完成寫(xiě)操作,所有客戶(hù)端從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)必須能夠看到剛剛寫(xiě)入的值。要維護(hù)數(shù)據(jù)的單個(gè)副本的假象,系統(tǒng)應(yīng)保障讀到的值是最近的、最新的,而不是來(lái)自陳舊的緩存或副本。換句話(huà)說(shuō),線(xiàn)性一致性是一個(gè) 新鮮度保證(recency guarantee)。為了闡明這個(gè)想法,我們來(lái)看看一個(gè)非線(xiàn)性一致系統(tǒng)的例子。


圖 9-1 展示了一個(gè)關(guān)于體育網(wǎng)站的非線(xiàn)性一致例子【9】。Alice 和 Bob 正坐在同一個(gè)房間里,都盯著各自的手機(jī),關(guān)注著 2014 年 FIFA 世界杯決賽的結(jié)果。在最后得分公布后,Alice 刷新頁(yè)面,看到宣布了獲勝者,并興奮地告訴 Bob。Bob 難以置信地刷新了自己的手機(jī),但他的請(qǐng)求路由到了一個(gè)落后的數(shù)據(jù)庫(kù)副本上,手機(jī)顯示比賽仍在進(jìn)行。

如果 Alice 和 Bob 在同一時(shí)間刷新并獲得了兩個(gè)不同的查詢(xún)結(jié)果,也許就沒(méi)有那么令人驚訝了。因?yàn)樗麄儾恢婪?wù)器處理他們請(qǐng)求的精確時(shí)刻。然而 Bob 是在聽(tīng)到 Alice 驚呼最后得分 之后,點(diǎn)擊了刷新按鈕(啟動(dòng)了他的查詢(xún)),因此他希望查詢(xún)結(jié)果至少與愛(ài)麗絲一樣新鮮。但他的查詢(xún)返回了陳舊結(jié)果,這一事實(shí)違背了線(xiàn)性一致性的要求。

什么使得系統(tǒng)線(xiàn)性一致?

線(xiàn)性一致性背后的基本思想很簡(jiǎn)單:使系統(tǒng)看起來(lái)好像只有一個(gè)數(shù)據(jù)副本。然而確切來(lái)講,實(shí)際上有更多要操心的地方。為了更好地理解線(xiàn)性一致性,讓我們?cè)倏磶讉€(gè)例子。

圖 9-2 顯示了三個(gè)客戶(hù)端在線(xiàn)性一致數(shù)據(jù)庫(kù)中同時(shí)讀寫(xiě)相同的鍵 x。在分布式系統(tǒng)文獻(xiàn)中,x 被稱(chēng)為 寄存器(register),例如,它可以是鍵值存儲(chǔ)中的一個(gè) ,關(guān)系數(shù)據(jù)庫(kù)中的一 ,或文檔數(shù)據(jù)庫(kù)中的一個(gè) 文檔

圖 9-2 如果讀取請(qǐng)求與寫(xiě)入請(qǐng)求并發(fā),則可能會(huì)返回舊值或新值

為了簡(jiǎn)單起見(jiàn),圖 9-2 采用了用戶(hù)請(qǐng)求的視角,而不是數(shù)據(jù)庫(kù)內(nèi)部的視角。每個(gè)柱都是由客戶(hù)端發(fā)出的請(qǐng)求,其中柱頭是請(qǐng)求發(fā)送的時(shí)刻,柱尾是客戶(hù)端收到響應(yīng)的時(shí)刻。因?yàn)榫W(wǎng)絡(luò)延遲變化無(wú)常,客戶(hù)端不知道數(shù)據(jù)庫(kù)處理其請(qǐng)求的精確時(shí)間 —— 只知道它發(fā)生在發(fā)送請(qǐng)求和接收響應(yīng)之間的某個(gè)時(shí)刻。1

在這個(gè)例子中,寄存器有兩種類(lèi)型的操作:


  • 表示客戶(hù)端請(qǐng)求讀取寄存器 x 的值,數(shù)據(jù)庫(kù)返回值 v。


    • 表示客戶(hù)端請(qǐng)求將寄存器 x 設(shè)置為值 v ,數(shù)據(jù)庫(kù)返回響應(yīng) r (可能正確,可能錯(cuò)誤)。

    在 圖 9-2 中,x 的值最初為 0,客戶(hù)端 C 執(zhí)行寫(xiě)請(qǐng)求將其設(shè)置為 1。發(fā)生這種情況時(shí),客戶(hù)端 A 和 B 反復(fù)輪詢(xún)數(shù)據(jù)庫(kù)以讀取最新值。A 和 B 的請(qǐng)求可能會(huì)收到怎樣的響應(yīng)?

    • 客戶(hù)端 A 的第一個(gè)讀操作,完成于寫(xiě)操作開(kāi)始之前,因此必須返回舊值 0。

    • 客戶(hù)端 A 的最后一個(gè)讀操作,開(kāi)始于寫(xiě)操作完成之后。如果數(shù)據(jù)庫(kù)是線(xiàn)性一致性的,它必然返回新值 1:因?yàn)樽x操作和寫(xiě)操作一定是在其各自的起止區(qū)間內(nèi)的某個(gè)時(shí)刻被處理。如果在寫(xiě)入結(jié)束后開(kāi)始讀取,則讀取處理一定發(fā)生在寫(xiě)入完成之后,因此它必須看到寫(xiě)入的新值。

    • 與寫(xiě)操作在時(shí)間上重疊的任何讀操作,可能會(huì)返回 01 ,因?yàn)槲覀儾恢雷x取時(shí),寫(xiě)操作是否已經(jīng)生效。這些操作是 并發(fā)(concurrent) 的。

    但是,這還不足以完全描述線(xiàn)性一致性:如果與寫(xiě)入同時(shí)發(fā)生的讀取可以返回舊值或新值,那么讀者可能會(huì)在寫(xiě)入期間看到數(shù)值在舊值和新值之間來(lái)回翻轉(zhuǎn)。這不是我們所期望的仿真 “單一數(shù)據(jù)副本” 的系統(tǒng)。2

    為了使系統(tǒng)線(xiàn)性一致,我們需要添加另一個(gè)約束,如 圖 9-3 所示

圖 9-3 任何一個(gè)讀取返回新值后,所有后續(xù)讀?。ㄔ谙嗤蚱渌蛻?hù)端上)也必須返回新值。

在一個(gè)線(xiàn)性一致的系統(tǒng)中,我們可以想象,在 x 的值從 0 自動(dòng)翻轉(zhuǎn)到 1 的時(shí)候(在寫(xiě)操作的開(kāi)始和結(jié)束之間)必定有一個(gè)時(shí)間點(diǎn)。因此,如果一個(gè)客戶(hù)端的讀取返回新的值 1,即使寫(xiě)操作尚未完成,所有后續(xù)讀取也必須返回新值。

圖 9-3 中的箭頭說(shuō)明了這個(gè)時(shí)序依賴(lài)關(guān)系??蛻?hù)端 A 是第一個(gè)讀取新的值 1 的位置。在 A 的讀取返回之后,B 開(kāi)始新的讀取。由于 B 的讀取嚴(yán)格在發(fā)生于 A 的讀取之后,因此即使 C 的寫(xiě)入仍在進(jìn)行中,也必須返回 1(與 圖 9-1 中的 Alice 和 Bob 的情況相同:在 Alice 讀取新值之后,Bob 也希望讀取新的值)。

我們可以進(jìn)一步細(xì)化這個(gè)時(shí)序圖,展示每個(gè)操作是如何在特定時(shí)刻原子性生效的。圖 9-4 顯示了一個(gè)更復(fù)雜的例子【10】。

在 圖 9-4 中,除了讀寫(xiě)之外,還增加了第三種類(lèi)型的操作:


表示客戶(hù)端請(qǐng)求進(jìn)行原子性的 比較與設(shè)置 操作。如果寄存器的當(dāng)前值等于,則應(yīng)該原子地設(shè)置為。如果不等于

  • ,則操作應(yīng)該保持寄存器不變并返回一個(gè)錯(cuò)誤。$r$ 是數(shù)據(jù)庫(kù)的響應(yīng)(正確或錯(cuò)誤)。

圖 9-4 中的每個(gè)操作都在我們認(rèn)為執(zhí)行操作的時(shí)候用豎線(xiàn)標(biāo)出(在每個(gè)操作的條柱之內(nèi))。這些標(biāo)記按順序連在一起,其結(jié)果必須是一個(gè)有效的寄存器讀寫(xiě)序列(每次讀取都必須返回最近一次寫(xiě)入設(shè)置的值)。

線(xiàn)性一致性的要求是,操作標(biāo)記的連線(xiàn)總是按時(shí)間(從左到右)向前移動(dòng),而不是向后移動(dòng)。這個(gè)要求確保了我們之前討論的新鮮度保證:一旦新的值被寫(xiě)入或讀取,所有后續(xù)的讀都會(huì)看到寫(xiě)入的值,直到它被再次覆蓋。

未完待續(xù)、兄弟們、欲知后事如何、傾聽(tīng)下回分解!


萬(wàn)字長(zhǎng)文-詳解分布式算法的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
扬州市| 长宁区| 涪陵区| 阜新市| 凉城县| 鄯善县| 石狮市| 梅州市| 项城市| 普定县| 丽江市| 昌黎县| 临沭县| 平江县| 老河口市| 鲁甸县| 安阳县| 惠来县| 嘉祥县| 德安县| 宿州市| 开原市| 唐山市| 怀柔区| 天峻县| 武胜县| 屯昌县| 江西省| 虎林市| 东乌| 松潘县| 柘荣县| 华坪县| 武邑县| 雅江县| 广德县| 博客| 三门峡市| 合阳县| 武胜县| 承德县|