主頁 > 後端開發 > 從2PC和容錯共識演算法討論zookeeper中的Create請求

從2PC和容錯共識演算法討論zookeeper中的Create請求

2023-06-27 07:42:28 後端開發

最近在讀《資料密集型應用系統設計》,其中談到了zookeeper對容錯共識演算法的應用,這讓我想到之前參考的zookeeper學習資料中,誤將容錯共識演算法寫成了2PC(兩階段提交協議),所以準備以此文對共識演算法和2PC做梳理和區分,也希望它能幫助像我一樣對這兩者有誤解的同學,

1. 2PC(兩階段提交協議)

兩階段提交 (two-phase commit) 協議是一種用于實作 跨多個節點的原子事務(分布式事務)提交 的演算法,它能確保所有節點提交或所有節點中止,并在某些資料庫內部使用,也以 XA事務 的形式在分布式服務中使用,

在 Java EE 中,XA事務使用 JTA(Java Transaction API) 實作,

2PC的實作

2PC包含 準備階段 和 提交階段 兩個階段,需要借助 協調者(事務管理器,如阿里巴巴的Seata)  來實作,參與分布式事務的資料庫節點為 參與者,當分布式服務中的節點準備提交時,協調者開始 準備階段:發送一個 準備請求 到每個節點,詢問它們是否能夠提交,然后協調者會跟蹤參與者的回應

  • 如果所有參與者都回答"是",表示它們已經準備好提交,那么協調者在 提交階段 發出 提交請求,分布式事務提交
  • 如果任意一個參與者回答"否",則協調者在 提交階段 中向所有節點發送 中止請求,分布式事務回滾

image.png

上圖是2PC提交成功的情況,我們來詳述下程序:

  1. 當服務啟動一個分布式事務時,它會向協調者請求一個事務ID,此事務ID是全域唯一的
  2. 在每個參與者上啟動單節點事務,每個單節點事務會持有這個全域事務 ID,所有的讀寫都是在這些單節點事務中各自完成的,如果在這個階段出現任何問題(節點崩潰或請求超時),則協調者或任何參與者都可以中止
  3. 當應用準備提交時,對應準備階段:協調者向所有參與者發送一個 準備請求,同樣也持有全域事務 ID ,如果任意一個請求失敗或超時,則協調者向所有參與者發送針對該事務 ID 的 中止請求,即2PC提交中止的情況
  4. 參與者收到 準備請求 時,需要確保在任意情況下都可以提交事務,這包括將所有事務資料寫入磁盤(出現故障,電源故障,或硬碟空間不足都不能是稍后拒絕提交的理由)以及檢查是否存在任何沖突或違反約束,通過向協調者回答 “是”,節點承諾這個事務一定可以不出差錯地提交,也就是說:參與者沒有實際提交,同時放棄了中止事務的權利
  5. 當協調者收到所有 準備請求 的答復時,會就 提交或中止事務 作出明確的決定(只有在 所有參與者 投贊成票的情況下才會提交),這里對應提交階段,協調者必須把這個提交或中止事務的決定 寫到磁盤上的事務日志中,記錄為 提交點(commit point) ,如果它隨后崩潰,能通過提交點進行恢復
  6. 一旦協調者的決定已經保存在事務日志中,提交或中止請求會發送給所有參與者,如果這個請求失敗或超時,協調者 必須永遠保持重試,直到成功為止,對于已經做出的決定,協調者不管需要多少次重試它都必須被執行

2PC協議中有兩個關鍵的 不歸路 需要注意:

  • 一旦協調者做出決定,這一決定是不可撤銷的
  • 參與者投票 “是” 時,它承諾它稍后肯定能夠提交(盡管協調者可能仍然選擇放棄),即使參與者在此期間崩潰,事務也需要在其恢復后提交,而且由于參與者投了贊成,它不能在恢復后拒絕提交

這些承諾保證了2PC的 原子性,

協調者失效的情況

如果 協調者失效 并且所有參與者都收到了準備請求并投了是,那么參與者什么都做不了只能等待,而且這種情況 解決方案 是等待協調者恢復或資料庫管理員介入操作來提交或回滾事務,當然如果在生產期間這需要承擔運維壓力,

所以,協調者在向參與者發送提交或中止請求 之前,將其提交或中止決定寫入磁盤上的事務日志(提交點),這樣就能在協調者發生崩潰恢復后,通過讀取其事務日志來確定所有 存疑事務 的狀態,任何在協調者事務日志中沒有提交記錄的事務都會被終止,因此兩階段提交在第二階段(提交階段)存在阻塞等待協調者恢復的情況,所以兩階段提交又被稱為 阻塞原子提交協議

番外:3PC

三階段提交協議也是應用在分布式事務提交中的演算法,它的提出是為了解決兩階段提交協議中存在的阻塞問題,它分為 CanCommit階段PreCommit階段 和 DoCommit階段,通過引入 參與者超時判斷機制 來解決2PC中存在的參與者依賴協調者的提交請求而阻塞導致的資源占用等問題,

上圖為在DoCommit階段,參與者判斷 DoCommit請求 超時情況的流程圖,我們詳述下它的避免阻塞的流程

  1. 服務在每個參與者上啟動單節點事務,當參與者準備提交時,對應CanCommit階段,協調者會向所有參與者發送 CanCommit請求,如果任意一個請求失敗或超時,則協調者會向所有參與者發送針對該事務的 中止請求,執行事務回滾
  2. 當協調者收到所有CanCommit請求的答復時,如果全是“是”那么則進入PreCommit階段,否則發送中止請求,執行事務回滾
  3. 進入PreCommit階段后,協調者會向所有參與者發送 PreCommit請求,同樣還是如果存在請求失敗或超時,會發送中止請求執行事務回滾
  4. 協調者收到所有PreCommit請求的答復時,如果全是“是”那么則進入DoCommit階段,否則發送中止請求,執行事務回滾
  5. 進入DoCommit階段后,協調者會向所有參與者發送 DoCommit請求,注意這里,如果某個參與者沒有收到該請求,它默認認為協調者會發送提交請求,那么便本地執行提交事務,從而避免阻塞

3PC雖然解決了2PC中存在的阻塞問題,但是也引入了新的問題:

  • 如果協調者在DoCommit階段回復的是中止請求,那么超時節點自顧自地提交事務就會發生資料不一致的情況
  • 通訊次數增加和實作相對復雜

3PC使原子提交協議變成非阻塞的,但是3PC 假定網路延遲和節點回應時間有限,在大多數具有無限網路延遲和行程暫停的實際系統中,它 并不能保證原子性,非阻塞原子提交需要一個 完美的故障檢測器 來以可靠的機制判斷一個節點是否已經崩潰,而在無限延遲的網路中,超時并不是一種可靠的故障檢測機制,因為即使節點沒有崩潰也會因為網路延遲而超時,出于這個原因,2PC仍然被使用,盡管存在協調者故障的問題,

2. 容錯共識演算法

容錯共識演算法用于 節點間資料同步,保證各個副本間資料的一致性和集群的高可用,它的通常形式是一個或多個節點可以 提議(propose)  某些值,而共識演算法 決定(decides)  采用其中的某個值,并讓這些節點就提議達成一致,共識演算法必須具備如下性質:

  • 一致同意:沒有兩個節點的決定不同
  • 完整性:沒有節點決定兩次
  • 有效性:如果節點決定了v值,那么v由該節點所提議
  • 終止性:由所有未崩潰的節點來最終決定值

終止性實質上是說:容錯共識演算法不能簡單地永遠閑坐著等待,而是需要根據大多數節點來達成一項決定,因此終止屬性也暗含著 不超過一半的節點崩潰或不可達 的資訊,

一致同意和完整性是共識的 核心思想,即所有節點決定了相同的結果并且決定后不能改變主意,

容錯共識演算法在節點集群內部都以某種形式使用一個領導者,并定義了一個 紀元編號(epoch number)  來確保在每個時代中,領導者都是唯一的,每當現任領導宕機時,節點間會開始一場投票,來選出一個新的領導,每次選舉被賦予一個新的紀元編號(全序且單調遞增),如果有兩個不同時代的領導者之間出現沖突(腦裂問題),那么帶有更高紀元編號的領導者說了算,領導者每想要做出的每一個決定,都必須將提議值發送給其他節點,并等待 法定人數 的節點回應并贊成提案,法定人數通常(但不總是)由多數節點組成(一般為過半),只有在沒有發現任何帶有更高紀元編號的領導者的情況下,一個節點才會投票贊成提議,

容錯共識演算法的局限性

  1. 節點在做出決定之前對提議進行投票的程序是一種同步復制
  2. 共識系統總是需要有 法定人數 的節點存活來保證運轉
  3. 大多數共識演算法假定參與投票的節點是固定的集合,這意味著你不能簡單的在集群中添加或洗掉節點
  4. 共識系統通常依靠 超時 來檢測失效的節點,在網路延遲高度變化的環境中,特別是在地理上散布的系統,經常發生一個節點由于暫時的網路問題,錯誤地認為領導者已經失效,雖然這種錯誤不會損害安全屬性,但頻繁的領導者選舉會導致糟糕的性能表現,所以共識演算法對網路問題比較敏感,而在面對不可靠的網路相關的共識演算法研究仍在進展中

3. 2PC和容錯共識演算法的區別

  1. 負責解決的問題不同:2PC解決的是分布式事務的一致性,各個節點存盤的資料各有不同,目標側重于保證事務的ACID;容錯共識演算法解決的是節點副本間資料的一致性和保證集群的高可用,節點間存盤的資料完全一致,目標側重于資料的復制和同步
  2. 每個提議通過要求的參與節點數不同:2PC要求 所有的參與者表決成功 才通過;容錯共識演算法只需要 遵循基于法定人數的表決 即可,這也是容錯共識演算法 終止屬性(由所有未崩潰的節點來決定最終值)  的體現
  3. 集群的高可用保證:2PC的協調者不是通過選舉產生的,而是單獨部署并人為指定的組件,所以它沒有選主機制,不具備高可用性;應用容錯共識演算法的集群領導者是通過選舉機制來指定的,并且在發生例外情況時(主節點宕機)能夠選出新的領導者,并進入一致的狀態,以此來保證集群的高可用

4. zookeeper中的一次Create請求

一些資料中會提到zookeeper在執行CRUD請求時,使用的是2PC,而 實際上它使用的是容錯共識演算法,我們以Create請求的流程為例(如下圖),來加深和記憶這一知識

  1. 客戶端發 create 請求到 Leader,即使請求沒落到 Leader 上,那么其他節點也會將寫請求轉發到 Leader
  2. Leader 會先發一個 提議(proposal)請求給各個 Follower,且自己將資料寫到本地檔案
  3. Follower 集群收到 proposal 請求后會將資料寫到本地檔案,寫成功后回傳給 Leader 一個 ack回復
  4. Leader 發現收到 ack 回復的數量為 法定人數(過半,包含當前 Leader 節點)時,則提交一個 commit 請求給各個 Follower 節點,發送 commit 請求就代表該資料在集群內同步情況沒有問題,并且 可以對外提供訪問 了,此時Leader會把資料寫到記憶體中
  5. Follower 收到 commit 請求后也會將資料寫到各自節點的記憶體中,同時Leader會將資料發給 Observer集群,通知 Observer集群 將資料寫到記憶體

巨人的肩膀

  • 《資料密集型應用系統設計》第九章:分布式事務與共識
  • 百度百科:三階段提交
  • 淺談分布式一致性協議之3PC
  • 分布式事務(2PC) vs 共識協議(Paxos/raft)
  • 《深度剖析zookeeper核心原理》
  • 原文收錄:GitHub-Enthusiasm

作者:京東物流 王奕龍

內容來源:京東云開發者社區

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556003.html

標籤:其他

上一篇:【numpy基礎】--聚合計算

下一篇:返回列表

標籤雲
其他(161625) Python(38254) JavaScript(25514) Java(18265) C(15238) 區塊鏈(8272) C#(7972) AI(7469) 爪哇(7425) MySQL(7269) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4606) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2437) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1985) HtmlCss(1972) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 從2PC和容錯共識演算法討論zookeeper中的Create請求

    最近在讀《資料密集型應用系統設計》,其中談到了zookeeper對容錯共識演算法的應用。這讓我想到之前參考的zookeeper學習資料中,誤將容錯共識演算法寫成了2PC(兩階段提交協議),所以準備以此文對共識演算法和2PC做梳理和區分,也希望它能幫助像我一樣對這兩者有誤解的同學。 ......

    uj5u.com 2023-06-27 07:42:28 more
  • 【numpy基礎】--聚合計算

    上一篇介紹的**通用計算**是關于多個`numpy`陣列的計算, 本篇介紹的**聚合計算**一般是針對單個資料集的各種統計結果,同樣,使用**聚合函式**,也可以避免繁瑣的回圈陳述句的撰寫。 # 元素的和 陣列中的元素求和也就是合計值。 ## 呼叫方式 **聚合計算**有兩種呼叫方式,一種是面向物件的 ......

    uj5u.com 2023-06-27 07:42:23 more
  • celery筆記八之資料庫操作定時任務

    > 本文首發于公眾號:Hunter后端 > 原文鏈接:[celery筆記八之資料庫操作定時任務](https://mp.weixin.qq.com/s/iM0VxVMagmRNeG2VIc01pg) 前面我們介紹定時任務是在 celery.py 中的 `app.conf.beat_schedule` ......

    uj5u.com 2023-06-27 07:41:40 more
  • 【promptulate專欄】ChatGPT框架——兩行代碼構建一個強大的論文

    > 本文節選自筆者博客:[https://www.blog.zeeland.cn/archives/019hasaa](https://www.blog.zeeland.cn/archives/019hasaa) # 前言 如果你經常閱讀論文,那么你肯定會遇到以下幾個問題: - 論文晦澀難懂看不明白 ......

    uj5u.com 2023-06-27 07:41:34 more
  • hovertool的基本使用

    # hovertool `HoverTool` 是 `Bokeh` 庫中的一個工具,它可以在滑鼠懸停在圖上時顯示資料。當滑鼠指標放在圖表的特定部分(比如散點圖的點或者線圖中的線的時候),該工具會顯示與該部分相關的附加資訊。 一般配套使用的是`from bokeh.plotting import fi ......

    uj5u.com 2023-06-27 07:41:26 more
  • 【numpy基礎】--聚合計算

    上一篇介紹的**通用計算**是關于多個`numpy`陣列的計算, 本篇介紹的**聚合計算**一般是針對單個資料集的各種統計結果,同樣,使用**聚合函式**,也可以避免繁瑣的回圈陳述句的撰寫。 # 元素的和 陣列中的元素求和也就是合計值。 ## 呼叫方式 **聚合計算**有兩種呼叫方式,一種是面向物件的 ......

    uj5u.com 2023-06-27 07:41:20 more
  • python dict del 和 pop 有什么區別

    del 和 pop 都可以從 Python 字典中洗掉一個鍵值對,不同之處在于它們的回傳值和錯誤處理方式。 del 陳述句可以直接洗掉字典中的一個鍵值對,語法如下: `del dict[key]` del 陳述句沒有回傳值,如果嘗試洗掉不存在的鍵,會拋出 KeyError 例外。 pop 方法可以洗掉字 ......

    uj5u.com 2023-06-27 07:41:16 more
  • 【python基礎】例外

    Python使用被稱為例外的特殊物件來管理程式執行期間發生的錯誤。每當發生執行錯誤時,Python都會創建一個例外物件。如果撰寫了處理該例外的代碼,程式將繼續執行;如果未對例外進行處理,程式將停止,并顯示一個Trackback,其中包含有關例外的報告。 # 1.try-except代碼塊 例外是用t ......

    uj5u.com 2023-06-27 07:41:06 more
  • 我將青春奉獻給了我喜歡的事情,卻讓我無法解決溫

    時間過的很快,3 年的疫情就這么過去了,留下的卻是緊張的社會氛圍。 目前已經在計算機行業 7 年了,記得那是 2015 年,當時我也才 15 歲,正在讀初二。那會特別喜歡別人的網站,比如卡盟,還有代掛等等別人的那些網站,然后我入坑了。我那會百度怎么做一個網站,然后搜出來需要學習 html,那時候,我 ......

    uj5u.com 2023-06-27 07:40:38 more
  • Java 網路編程 —— 安全網路通信

    ## SSL 簡介 SSL(Secure Socket Layer,安全套接字層)是一種保證網路上的兩個節點進行安全通信的協議。IETF(Interet Engineering Task Force)國際組織對 SSL 作了標準化,制定了 RFC2246 規范,并將其稱為傳輸層安全(Transpor ......

    uj5u.com 2023-06-27 07:40:33 more