分布式強一致性有哪些實現方案,2PC是不是強一致?

時間 2021-05-10 09:35:05

1樓:Augustus Fengh

一般我們說的強一致性,指的其實是「consensus」方面的問題,和 2pc 解決的事務問題不是一回事;

如果你指的是一致性問題嘛,那 raft、paxos 都能做到,不過需要加上限制(比如 lease + 讀主寫主),因為本質上強一致是一系列「讀」和「寫」可見內容的約束

如果你指的是事務方面的問題(應該叫隔離性了),那你說的沒錯,2pc 確實能保證多個 rm 要麼都做了,要麼都沒沒做;但是,rm-1 提交了,rm-2 還沒提交(提交中),你讀的請求如果落到 rm-2,你會讀到什麼呢?

2樓:寵寵神

不是乙個層面的問題。分布式環境中的一致性是多個節點對同乙個key對應的value認知達成一致;2pc處理的是分布式環境中原子性的問題,保證多個節點的多個key對應的value的步調一致地變化,不會出現某個key變了某個key不變的中間狀態。具體可參考spanner,2pc+paxos。

3樓:Bowen Xiao

先理清一些概念。現在講分布式強一致性,大多數時候是在講多副本之間的資料讀寫一致性,至於併發事務讀寫的一致性(或者叫可見性),大家一般叫做事務隔離級別。比如TiDB使用Raft協議來達成強一致性,強調的是多副本也不會讀到過期資料,當然Raft設計裡也有2PC的影子,所以你說的有一定道理。

2PC在資料庫裡運用最廣泛的還是事務提交的方法之一,主要實現分布式資料庫的事務ACD(少了I),當然這裡的C (Consistency) 和你講的 "強一致性" 不一樣。(題外話:其實單機資料庫裡也有2PC的概念,比如MySQL先寫Redo Log再寫Bin Log。

)要說強一致性和2PC完全沒關係嗎?肯定不對,分布式強一致性還有一些併發事務控制的語義(我還沒見過哪個分布式資料庫號稱提供強一致性,但是不提供可重複讀以上隔離級別的),併發事務控制當然跟2PC有關。要說他們完全相等嗎?

也不太對,因為2PC更多強調的是事務的原子性,執行過程中的可見性沒有解決,也不去處理多副本間的資料一致性,只是解決了事務的提交問題。

綜上,我認為要講強一致性的實現方案,既要講多副本的資料一致性,也要講事務的併發處理。

事務的難點主要有讀寫衝突處理 (Concurrency Control) 和提交 (當然這種分法也不太對,提交也涉及讀寫衝突)。先宣告乙個觀點,分布式系統最重要的是確定時間,所以時鐘問題是2個部分都沒辦法迴避的問題。既然你提到了2PC,那我們就先講一下提交。

我的觀點是和 @Ed Huang 的差不多的,現階段幾乎所有的分布式事務提交都是通過2PC或者2PC的變種提交,所以這個領域未來大概率也很難有純理論上的創新了,硬體可能會drive一些方向。一些主流分布式資料庫會做很多優化,比如快取寫內容 + 樂觀鎖(TiDB),Percolator事務模型(TiDB),Paxos Commit,CockRoachDB做了Write Intent (非同步完成事務最終提交), 1PC (GoldenDB,本質上還是可以分為2個Phase),這些技術的特點是理論上早已成熟,工程上難點特別多。

談完事務提交,不得不講讀寫衝突處理。這裡想講點歷史。以前的資料庫壬實現事務,往往會搞乙個中心化的lock manager管理資料資源。

但是管理鎖這個東西是非常麻煩的事情,因為這意味著你要往系統裡加死鎖檢測的component。InnoDB (2PL + MVCC) 的設計出來後,影響了很多人,也是很經典的設計:MVCC降低了讀寫阻塞度,2PL一定程度上降低了資源管理難度,但是這種設計不得不維護乙個中心化的活躍事務列表,容易成為單點,MySQL這種單機資料庫當然沒什麼所謂,但是可以看到TiDB/CockRoachDB都沒有採用這種設計。

可以把這種設計叫做Snapshot,因為它確實像是維護了過去版本的Snapshot,事務要查詢的時候就undo到對應階段返回資料。現在比較主流的衝突處理方案是Timestamp,它比較依賴時鐘的準確性:時鐘越準,系統設計者就可以多偷一點懶。

比如Spanner的寫等待 (commit-wait),拿到提交時間戳後等待乙個時間區間再真正寫盤 ,通過等待來消除不同節點時間的不一致性。TiDB和CockRoachDB其實本質上都處理不了讀寫衝突:TiDB沒有維護活躍事務列表,所以理論上,事務A 「Prewrite階段加的鎖」會阻塞事務B讀同一條資料,因為事務B無法判斷自己的start_ts是否大於事務A的commit_ts,而這是事務隔離性的基礎;CockRoachDB支援SSI,落入不確定讀寫區間後會自動重啟事務。

最後再講一下多副本間的一致性。這個基本就沒有太多選擇了。共識演算法靠譜的就2個,Paxos和Raft。

Raft優點是實現相對簡單,Paxos是理論吞吐上限更高,但是工程難度巨大,所以一般是大公司養人做。想做一套Raft的話,有很多可以參考,比如etcd的Raft,TiDB的Raft當初就是從這port的乙個Rust版本。Raft也有很多優化點,TiDB官方部落格偶爾會寫一些,比如Follower Read,Multi-Raft,Batch and Pipeline等等,這裡不多說了。

4樓:someoneATwu

2PC解決的是分布式系統中事務的原子性,即事務基本特性ACID中的A。也就是說,2PC保證了分布式事務要麼在所有節點(每個節點所做資料修改各不相同)提交要麼都回滾。A的保證與否,會影響到事務的C。

事務裡面也有一致性概念(ACID中的C),主要保證事務操作後保持原有的資料的約束,比如轉賬事務完成之後,轉賬的雙方不能的總額不能多也不能少。

我理解題主這裡指的分布式強一致應該指的是在多副本的分布式系統中,各個副本間的資料一致性。強一致保證一旦修改了某個副本上的值,這個值在後續一定要能夠被讀到,即使可能查的不是當時修改值的那個副本節點。

5樓:狼王程式設計

對於分布式事務,相信所有人都應該很了解,為什麼會有分布式事務?無論是資料量導致的分庫,還是現在微服務盛行的場景都是他出現的原因。

無非是XA、2PC、3PC、TCC

但是,我認為這東西,只是適用於面試和理論的了解,你真要說這些方案實際生產中有人用嗎?

有,但是會實現的更簡單,不會套用理論來實現,大廠有大廠的解決方案,中小公司用框架或者壓根就不存在分布式事務的問題。

那,為什麼還要寫這個?

要說分布式事務,首先還是從事務的基本特徵說起。

A原子性:在事務的執行過程中,要麼全部執行成功,要麼都不成功。

C一致性:事務在執行前後,不能破壞資料的完整性。一致性更多的說的是通過AID來達到目的,資料應該符合預先的定義和約束,由應用層面來保證,還有的說法是C是強行為了ACID湊出來的。

I隔離性:多個事務之間是互相隔離的,事務之間不能互相干擾,涉及到不同事務的隔離級別的問題。

D永續性:一旦事務提交,資料庫中資料的狀態就應該是永久性的。

XA(eXtended Architecture)是指由X/Open 組織提出的分布式事務處理的規範,他是乙個規範或者說是協議,定義了事務管理器TM(Transaction Manager),資源管理器RM(Resource Manager),和應用程式。

事務管理器TM就是事務的協調者,資源管理器RM可以認為就是乙個資料庫。

XA定義了規範,那麼2PC和3PC就是他的具體實現方式。

2PC叫做二階段提交,分為投票階段和執行階段兩個階段。

投票階段

TM向所有的參與者傳送prepare請求,詢問是否可以執行事務,等待各個參與者的響應。

這個階段可以認為只是執行了事務的SQL語句,但是還沒有提交。

如果都執行成功了就返回YES,否則返回NO。

執行階段

執行階段就是真正的事務提交的階段,但是要考慮到失敗的情況。

如果所有的參與者都返回YES,那麼就執行傳送commit命令,參與者收到之後執行提交事務。

反之,只要有任意乙個參與者返回的是NO的話,就傳送rollback命令,然後執行回滾的操作。

2PC的缺陷

同步阻塞,可以看到,在執行事務的過程當中,所有資料庫的資源都被鎖定,如果這時候有其他人來訪問這些資源,將會被阻塞,這是乙個很大的效能問題。

TM單點問題,只要乙個TM,一旦TM宕機,那麼整個流程無法繼續完成。

資料不一致,如果在執行階段,參與者腦裂或者其他故障導致沒有收到commit請求,部分提交事務,部分未提交,那麼資料不一致的問題就產生了。

既然2PC有這麼多問題,所以就衍生出了3PC的概念,也叫做三階段提交,他把整個流程分成了CanCommit、PreCommit、DoCommit三個步驟,相比2PC,增加的就是CanCommit階段。

CanCommit

這個階段就是先詢問資料庫是否執行事務,傳送乙個canCommit的請求去詢問,如果可以的話就返回YES,反之返回NO。

PreCommit

這個階段就等同於2PC的投票階段了,傳送preCommit命令,然後去執行SQL事務,成功就返回YES,反之返回NO。

但是,這個地方的區別在於參與者有了超時機制,如果參與者超時未收到doCommit命令的話,將會預設去提交事務。

DoCommit

DoCommit階段對應到2PC的執行階段,如果上乙個階段都是收到YES的話,那麼就傳送doCommit命令去提交事務,反之則會傳送abort命令去中斷事務的執行。

相比2PC的改進

對於2PC的同步阻塞的問題,我們可以看到因為3PC加入了參與者的超時機制,所以原來2PC的如果某個參與者故障導致的同步阻塞的問題時間縮短了,這是乙個優化,但是並沒有完全避免。

第二個單點故障的問題,同樣因為超時機制的引入,一定程度上也算是優化了。

但是資料不一致的問題,這個始終沒有得到解決。

舉個栗子:

在PreCommit階段,某個參與者發生腦裂,無法收到TM的請求,這時候其他參與者執行abort事務回滾,而腦裂的參與者超時之後繼續提交事務,還是有可能發生資料不一致的問題。

那麼,為什麼要加入DoCommit這個階段呢?就是為了引入超時機制,事先我們先確認資料庫是否都可以執行事務,如果都OK,那麼才會進入後面的步驟,所以既然都可以執行,那麼超時之後說明發生了問題,就自動提交事務。

TCC的模式叫做Try、Confirm、Cancel,實際上也就是2PC的乙個變種而已。

實現這個模式,乙個事務的介面需要拆分成3個,也就是Try預佔、Confirm確認提交、最後Cancel回滾。

對於TCC來說,實際生產我基本上就沒看見過有人用,考慮到原因,首先是程式設計師的本身素質參差不齊,多個團隊協作你很難去約束別人按照你的規則來實現,另外一點就是太過於複雜。

如果說有簡單的應用的話,庫存的應用或許可以算做是乙個。

一般庫存的操作,很多實現方案裡面都會會在下單的時候先預佔庫存,下單成功之後再實際去扣減庫存,最終如果發生了異常再回退。

凍結、預佔庫存就是2PC的準備階段,真正下單成功去扣減庫存就是2PC的提交階段,回滾就是某個發生異常的回滾操作,只不過在應用層面來實現了2PC的機制而已。

分布式系統常用的一致性演算法有哪些?

一致性這個翻譯是有問題的,應該用共識比較好consistency vs consensus一致性容易混淆使用replication 方法多備份資料來防止資料丟失的情況。共識系統則很清晰,就是多個參與者針對某乙個議題達成一致意見。 satanson 其實應該叫分布式共識 distributed con...

分布式系統中的一致性hash為什麼叫一致性hash?

三毛 先寫個大概,有人看再仔細展開。要理解一致性雜湊的一致性的含義,首先要知道一致性雜湊的典型應用場景,也就是分布式快取。比如我們有三颱伺服器,那麼需要快取的資料可以通過簡單的膜3取餘,來決定快取到哪乙個伺服器上。這樣會有個問題,也就是當伺服器數量變化的時候 比如現有伺服器太少,需要新加 我們需要改...

分布式事務中的最終一致具體應該如何實現?

首先最終一致性就不是採用遠端呼叫這種方式來實現的,你如果要用遠端呼叫來實現,那就上全域性事務框架,沒有什麼其他的好辦法。最終一致性目前都是通過訊息補償投遞來實現的,在消費端做冪等性校驗,投遞端保障投遞正確。 kimmking 分布式系統中的資料一致性和效能怎麼權衡?kimmking的回答 知乎 分布...