分布式系統的一致性與共識算法(三)

順序一致性(Sequential Consistency)

ZooKeeper

一種說法是ZooKeeper是最終一致性,因為由于多副本、以及保證大多數成功的ZAB協議,當一個客戶端進程寫入一個新值,另外一個客戶端進程不能保證馬上就能讀到這個值,但是能保證最終能讀取到這個值。另外一種說法是ZooKeeper的ZAB協議類似于Paxos,提供了強一致性。但這兩種說法都不準確,ZooKeeper文檔中明確寫明它的一致性是Sequential Consitency即順序一致。ZooKeeper中針對同一個FollowerA提交的寫請求request1、request2,某些Follower雖然可能不能在提交成功后立即看到(也就是強一致性),但經過自身與Leader之間的同步后,這些Follower在看到這連個請求時,一定是先看到request1,request2,兩個請求之間不會亂序,即順序一致性。
其實,實現ZooKeeper的一致性更復雜一些,ZooKeeper的讀操作是sequential consistency的,ZooKeeper的寫操作是linearizability的,關于這個說法,ZooKeeper的官方文檔中沒有寫出來,但是在社區的郵件組有詳細的討論。ZooKeeper的論文《Modular Composition of Coordination Services》中也有提到這個觀點。

總結一下,可以這么理解ZooKeeper:從整體(read操作 + write操作)上來說是sequential consistency,寫操作實現了Linearizability

線性一致性(Linearizability)

線性一致性又被稱為強一致性、嚴格一致性、原子一致性。是程序能實現的最高的一致性模型,也是分布式系統用戶最期望的一致性。CAP中的C一般就指它。順序一致性中進程只關心大家認同的順序一樣就行,不需要與全局時鐘一致,線性就更嚴格,從這種偏序(partial order)要達到全序(total order)要求是:

  • 1.任何一次讀都能讀到某個數據的最近一次寫的數據
  • 2.系統中的所有進程,看到的操作順序,都與全局時鐘下的順序一致。

以前面講的例3繼續討論:

B1看到X的新值,C1反而看到的是舊值,即對用戶來說,x的值發生了回跳

在線性一致的系統中,如果B1看到的x值為1,則C1看到的值也一定為1。任何操作在該系統生效的時刻都對應時間軸上的一個點。如果我們把這些時刻連接起來,如圖中紫線所示,則這條線會一致沿時間軸向前,不會反向回跳。所以任何操作都需要互相比較決定,誰發生在前,誰發生在后。例如B1發生在A0之前,C1發生在A0之后,而在前面順序一致性模型中,我們無法比較諸如B1和A0的先后關系。線性一致性的理論在軟件上有哪些體現呢?
在這里插入圖片描述

etcd與raft

上面提到ZooKeeper的寫是線性一致性,讀是順序一致性。而etecd讀寫都做了線性一致,即etcd是標準的強一致性保證。
etcd是基于raft來實現的,raft是共識算法,雖然共識和一致性的關系很微妙,經常一起討論,但共識算法只是提供基礎,要實現線性一致還需要在算法之上做出更多的努力如庫封裝,代碼實現等。如Raft中對于一致性讀給出了兩種方案,來保證處理這次讀請求的一定是Leader:

  • 1.ReadIndex
  • 2.LeaseRead
    基于Raft的軟件有很多,如etcd、tidb、SOFAJRaft等,這些軟件在實現一致讀時都是基于這兩種方式。這里對ReadIndex和Lease Read做下解釋,即etcd中線性一致性讀的具體實現。由于在Raft算法中,寫操作成功僅僅意味著日志達成了一致(已經落盤),而并不能確保當前狀態機也已經apply了日志。狀態機apply日志的行為在大多數Raft算法的實現中都是異步的,所以此時讀取狀態機并不能準確反映數據的狀態,很可能會讀到過期數據。
    基于以上這個原因,要想實現線性一致性讀,一個交為簡單通用的策略就是:每次讀操作的時候記錄此時集群的committed index,當狀態機的apply index大于或等于committed index時才讀取數據并返回。由于此時狀態機已經把度請求發起時的已提交日志進行了apply動作,所以此時狀態機的狀態就可以響應度請求發起時的狀態,符合線性一致性讀的要求。這便是ReadIndex算法。
    那如何準確獲取集群的committed index?如果獲取到的committed index不準確,那么以不準確的committed index為基準的ReadIndex算法講可能拿到過期數據。為了確保committed index的準確,我們需要:
  • 1.讓leader來處理讀請求
  • 2.如果follower收到讀請求,將請求forward給leader
  • 3.確保當前leader仍然是leader
    leader會發起一次廣播請求,如果還能收到大多數節點的應答,則說明此時leader還是leader.這點非常關鍵,如果沒有這個環節,leader有可能因網絡分區等原因已不再是leader,度請求依然由過期的leader處理,那么久將有可能讀到過去的數。這樣,我們從leader獲取的committed index久作為此次讀請求的ReadIndex.

以網絡分區為例:

在這里插入圖片描述

  • 1.初始狀態時集群有5個節點:A、B、C、D和E,其中A是leader;
  • 2.發生網絡隔離,集群被分割成兩部分,一個A和B,另外一個是C、D、E。雖然A會持續向其他介個節點發送headerbeat,但由于網絡隔離,C、D、E將無法接收到A的heartbeat。默認地,A不處理向follower節點發送heartbeat失敗(此處為網絡超時)的情況(協議沒有明確說明heartbeat是一個必須收到follower ack的雙向過程);
  • 3.C、D、E組成的分區在經過一定時間沒有收到leader的heartbeat后,觸發election timeout,此時C成為leader.此時,原來5節點集群因網絡分區分割成兩個集群:小集群A和B;大集群C、D、E,C為leader
  • 4.此時客戶端進行讀寫操作。在Raft算法中,客戶端無法感知集群的leader變化(更無法感知服務端有網絡隔離的事件發生)。客戶端在向集群發起讀寫請求時。如果客戶端一開始選擇C節點,并成功寫入數據(C節點集群已經commit操作日志),然后因客戶端某些原因(比如斷線重連),選擇節點A進行讀操作。由于A并不知道另外3個節點已經組成當前集群的大多數并寫入了新的數據,所以節點A無法返回準確的數據。此時客戶端將讀到過期數據。不過相應地,如果此時客戶端向節點A發起寫操作,那么寫操作將失敗,因為A因網絡隔離無法收到大多數節點的寫入響應
  • 5.針對上述情況,其實節點C、D、E組成的新集群才是當前5節點集群中大多數,讀寫操作應該發生在這個集群中而不是原來的小集群(節點A和B).如果此時節點A能感知它已經不再是集群的leader,那么節點A將不再處理讀寫請求。于是,我們可以在leader處理讀寫請求時,發起一次check quorum環節:
    leader向集群的所有節點發起廣播。當leader還能收到集群大多數節點的響應,說明leader還是當前集群的有效leader,擁有當前集群完整的數據,否則,讀請求失敗,將迫使客戶端崇訓選擇新節點進行讀寫

這樣一來,Raft算法久可以保障CAP中的C和P,但無法保障A:網絡分區時并不是所有節點都可以響應請求,少數節點的分區將無法進行服務,從而不符合Availablility。因此,Raft算法是CP類型的一致性算法

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13036.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13036.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13036.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

我的第一個網頁:武理天協

1. html代碼 1.1 首頁.html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>武理天協</title><link rel"stylesheet" href"./style.css"><link rel"stylesh…

【車載開發系列】SID$11服務配置

【車載開發系列】SID$11服務配置 前言 ECUReset(ECU重置),ECU作為Server端,執行Client發送來ECU Reset請求中重啟的類型(通過子服務區分)。對于UDS協議關于處理該請求的邏輯,沒有強制性定義。 Step1:SID和SubFunction的追加 BasicEditor→Dcm→DcmConfigSet→DcmDs…

vs2019 c++里用 typeid() . name () 與 typeid() . raw_name () 測試數據類型的區別

&#xff08;1&#xff09; 都知道&#xff0c;在 vs2019 里用 typeid 打印的類型不大準&#xff0c;會主動去掉一些修飾符&#xff0c; const 和引用 修飾符會被去掉。但也可以給咱們驗證學到的代碼知識提供一些參考。那么今天發現其還有 raw_name 成員函數&#xff0c;這個函…

AES分組密碼

一、AES明文和密鑰位數 RIJNDAEL 算法數據塊長度和密鑰長度都可獨立地選定為大于等于 128 位且小于等于 256 位的 32 位的任意倍數。 而美國頒布 AES 時卻規定數據塊的長度為 128 位、密鑰的長度可分別選擇為 128 位&#xff0c; 192 位或 256 位 1.1 狀態 中間結果叫做狀態…

建模:3dmax

3Dmax 制作模型和動畫&#xff08;橘肉&#xff09;&#xff1b; RizomUV 對模型進行展UV&#xff08;橘皮&#xff09;&#xff1b; Substance Painter 紋理手繪&#xff08;給橘皮制定想要的皮膚&#xff09;&#xff1b; 1.基礎 1.1可編輯多邊形、可編輯樣條線 體、面都需要…

Polylang Pro插件下載:多語言網站構建的終極解決方案

在全球化的今天&#xff0c;多語言網站已成為企業拓展國際市場的重要工具。然而&#xff0c;創建和管理一個多語言網站并非易事。幸運的是&#xff0c;Polylang Pro插件的出現&#xff0c;為WordPress用戶提供了一個強大的多語言解決方案。本文將深入探討Polylang Pro插件的功能…

linux上git 使用方法

一、git上新建倉庫 在git上新建倉庫&#xff0c;并命名 二、本地初始化 //命令行 ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" //ssh查看 cd /root/.ssh/ vim rsa.pub //復制后粘貼進git網頁設置里的ssh key //測試設置是否成功 ssh -T gitgithub.com/…

暴力數據結構之二叉樹(堆的相關知識)

1. 堆的基本了解 堆&#xff08;heap&#xff09;是計算機科學中一種特殊的數據結構&#xff0c;通常被視為一個完全二叉樹&#xff0c;并且可以用數組來存儲。堆的主要應用是在一組變化頻繁&#xff08;增刪查改的頻率較高&#xff09;的數據集中查找最值。堆分為大根堆和小根…

Spring事務的實現原理

Spring事務原理 Spring框架支持對于事務的管理功能&#xff0c;開發人員使用Spring框架能極大的簡化對于數據庫事務的管理操作&#xff0c;不必進行手動開啟事務&#xff0c;提交事務&#xff0c;回滾事務&#xff0c;就是在配置文件或者項目的啟動類配置Spring事務相關的注解…

什么是最大路徑?什么是極大路徑?

最近學習中&#xff0c;在這兩個概念上出現了混淆&#xff0c;導致了一些誤解&#xff0c;在此厘清。 最大路徑 在一個簡單圖G中&#xff0c;u、v之間的距離 d ( u , v ) min ? { u 到 v 的最短路的長度 } d(u,v) \min \{ u到v的最短路的長度 \} d(u,v)min{u到v的最短路的…

wefaf

c語言中的小小白-CSDN博客c語言中的小小白關注算法,c,c語言,貪心算法,鏈表,mysql,動態規劃,后端,線性回歸,數據結構,排序算法領域.https://blog.csdn.net/bhbcdxb123?spm1001.2014.3001.5343 給大家分享一句我很喜歡我話&#xff1a; 知不足而奮進&#xff0c;望遠山而前行&am…

使用Bash腳本和Logrotate實現Nginx日志切割

Nginx是一個廣泛使用的高性能Web服務器&#xff0c;它能夠處理大量的并發連接&#xff0c;但同時也會生成大量的日志文件。為了有效管理這些日志文件并確保系統的正常運行&#xff0c;我們需要定期對Nginx的日志文件進行切割和歸檔。本文將介紹如何使用Bash腳本和Logrotate來實…

每天Get一個小技巧:用DolphinScheduler實現隔幾天調度

轉載自tuoluzhe8521 這篇小短文將教會你如何使用Apache DolphinScheduler實現隔幾天調度&#xff0c;有此需求的小伙伴學起來&#xff01; 1 場景分析 DolphinScheduler定時器模塊-定時調度時每3秒|每3分鐘|每3天這種定時&#xff0c;不能夠跨分鐘&#xff0c;跨小時&#x…

【C++】:string類的基本使用

目錄 引言一&#xff0c;string類對象的常見構造二&#xff0c;string類對象的容量操作三&#xff0c;string類對象的訪問及遍歷操作四&#xff0c;string類對象的修改操作五&#xff0c;string類非成員函數六&#xff0c;整形與字符串的轉換 引言 string 就是我們常說的"…

如何對SQL Server中的敏感數據進行加密解密?

為什么需要對敏感數據進行加密&#xff1f; 近幾年有不少關于個人數據泄露的新聞&#xff08;個人數據通常包含如姓名、地址、身份證號碼、財務信息等&#xff09;&#xff0c;給事發公司和被泄露人都帶來了不小的影響。 許多國家和地區都出臺了個人數據保護的法律法規&#…

Unity Animation--動畫窗口指南(使用動畫視圖)

Unity Animation--動畫窗口指南&#xff08;使用動畫視圖&#xff09; 使用動畫視圖 window -> Animation 即可打開窗口 查看GameObject上的動畫 window -> Animation -> Animation 默認快捷鍵 Ctrl 6 動畫屬性列表 在下面的圖像中&#xff0c;“動畫”視圖&am…

思科模擬器--2.靜態路由和默認路由配置24.5.15

首先&#xff0c;創建三個路由器和兩個個人電腦。 接著&#xff0c;配置兩臺電腦的IP&#xff0c;子網掩碼和默認網關 對Router 0&#xff0c;進行以下命令&#xff1a; 對Router進行以下命令&#xff1a; 對Router2進行以下命令&#xff1a; 本實驗完成。 驗證&#xff1a;PC…

Vue3+ts(day06:路由)

學習源碼可以看我的個人前端學習筆記 (github.com):qdxzw/frontlearningNotes 覺得有幫助的同學&#xff0c;可以點心心支持一下哈&#xff08;筆記是根據b站上學習的尚硅谷的前端視頻【張天禹老師】&#xff0c;記錄一下學習筆記&#xff0c;用于自己復盤&#xff0c;有需要學…

【ARMv8/v9 系統寄存器 5 -- ARMv8 Cache 控制寄存器 SCTRL_EL1 使用詳細介紹】

關于ARM Cache 詳細學習推薦專欄&#xff1a; 【ARM Cache 專欄】 【ARM ACE Bus 與 Cache 專欄】 文章目錄 ARMv8/v9 Cache 設置寄存器ARMv8 指令 Cache 使能函數測試代碼 ARMv8/v9 Cache 設置寄存器 關于寄存器SCTRL_EL1 的詳細介紹見文章&#xff1a;【ARMv8/v9 異常模型入…

純正英語新聞 5.15

seizing territory &#xff1a;奪取領土 battlefield:戰場 shrinking&#xff1a;縮小 paramedic&#xff1a;醫護人員 mercilessly destroy&#xff1a;無情地摧殘 blown up&#xff1a;炸毀 northern outskirts :北郊 terrified&#xff1a;害怕 shelling&#xff…