分佈式事務(DTS)及分佈式系統原理分析

軟件 併發控制 編程語言 DTS 圖靈學院 圖靈學院 2017-10-04

引言

分佈式系統(distributed system)是建立在網絡之上的軟件系統。正是因為軟件的特性,所以分佈式系統具有高度的內聚性和透明性。因此,網絡和分佈式系統之間的區別更多的在於高層軟件(特別是操作系統),而不是硬件。內聚性是指每一個數據庫分佈節點高度自治,有本地的數據庫管理系統。透明性是指每一個數據庫分佈節點對用戶的應用來說都是透明的,看不出是本地還是遠程。在分佈式數據庫系統中,用戶感覺不到數據是分佈的,即用戶不須知道關係是否分割、有無副本、數據存於哪個站點以及事務在哪個站點上執行等。

一、分佈式系統/SOA/微服務架構的特點:

在大型分佈式系統中要同時能夠滿足,分佈式一致性(Consistency)、可用性(Availability)和分區容忍性(Partitiontolerance),是不存在的。在大多數情況下只能滿足其中的2項,而實現系統的最終一致性(Base理論)。

( 1 ) CAP特點:

a.一致性(Consistency):( 同樣數據在分佈式系統的各個節點上都是一致的)

b.可用性(Availability):( 所有在分佈式系統活躍的節點都能夠處理操作且能響應查詢)

c.分區容忍性(Partition Tolerance) :(如果出現了網絡故障、一部分節點無法通信,但是系統仍能夠工作)

( 2 ) ACID特點:

a.原子性(Atomicity)

一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。

b.一致性(Consistency)

事務的一致性指的是在一個事務執行之前和執行之後數據庫都必須處於一致性狀態。如果事務成功地完成,那麼系統中所有變化將正確地應用,系統處於有效狀態。如果在事務中出現錯誤,那麼系統中的所有變化將自動地回滾,系統返回到原始狀態。

c.隔離性(Isolation)

指的是在併發環境中,當不同的事務同時操縱相同的數據時,每個事務都有各自的完整數據空間。由併發事務所做的修改必須與任何其他併發事務所做的修改隔離。事務查看數據更新時,數據所處的狀態要麼是另一事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會查看到中間狀態的數據。

d.持久性(Durability)

指的是隻要事務成功結束,它對數據庫所做的更新就必須永久保存下來。即使發生系統崩潰,重新啟動數據庫系統後,數據庫還能恢復到事務成功結束時的狀態。

二、分佈式事務的基本介紹

分佈式事務服務(Distributed Transaction Service,DTS)是一種分佈式事務框架,用來確保在大規模分佈式/微服務環境下端到端業務操作的最終一致性。

由CAP定理可知,任何大型的分佈式系統/微服務在一致性、可用性和分區容忍這三點上只能保證其中的兩點。由於在分佈式系統中經常發生丟包、網絡故障,分區容忍性是必須要滿足的,同時為了兼顧高可用性,絕大部分系統都將強一致性需求轉化成最終一致性的需求,並通過冪等機制保證了數據的最終一致性。

三、常用的分佈式技術介紹

( 1 ) 本地消息表(經典的ebay模式)

該方案的核心思想在於分佈式系統在處理任務時通過消息日誌的方式來異步執行。消息日誌可以存儲至本地文本、數據庫或消息隊列,然後再通過業務規則定時任務或人工自動重試。以在線支付系統的跨行轉賬為例:

第一步,偽代碼如下,對用戶id為A的賬戶扣款1000元,通過本地事務將事務消息(包括本地事務id、支付賬戶、收款賬戶、金額、狀態等)插入至消息表:

Begin transaction

update user_account set amount = amount - 1000 where userId = 'A'

insert into trans_message(xid,payAccount,recAccount,amount,status) values(uuid(),'A','B',1000,1);

end transaction

commit;

第二步,通知對方用戶id為B,增加1000元,通常通過消息MQ的方式發送異步消息,對方訂閱並監聽消息後自動觸發轉賬的操作;這裡為了保證冪等性,防止觸發重複的轉賬操作,需要在執行轉賬操作方新增一個trans_recv_log表用來做冪等,在第二階段收到消息後,通過判斷trans_recv_log表來檢測相關記錄是否被執行,如果未被執行則會對B賬戶餘額執行加1000元的操作,並會將該記錄增加至trans_recv_log,事件結束後通過回調更新trans_message的狀態值。

( 2 ) 消息中間件

a.非事務消息中間件

這裡仍然以上面跨行轉賬為例,我們很難保證在扣款完成之後對MQ投遞消息的操作就一定能成功。這樣一致性似乎很難保證。以下偽代碼說明了消息投遞的異常:

try{

boolean result = dao.update(model);//更新數據庫失敗拋出異常

if(result){

mq.send(model);//如果MQ超時或者接收方處理失敗,拋出異常

}

}catch(Exception ex){

rollback();//如果異常回滾

}

對於以上的運行情況主要有以下幾種:

操作數據庫成功,向MQ中投遞消息也成功,該屬於正常情況,一切都OK。

操作數據庫失敗,不會向MQ中投遞消息了。

操作數據庫成功,但是向MQ中投遞消息時失敗,向外拋出了異常,剛剛執行的更新數據庫的操作將被回滾。

從上面分析的幾種情況來看,基本上能確保,發送消息的可靠性。我們再來分析下消費者端的問題:

接收者取出消息後,消費者對應的業務操作要執行成功。如果業務執行失敗,消息不能失效或者丟失。需要保證消息與業務操作一致。

儘量確保消息的冪等性。如果出現重複消息投遞,能夠進行冪等而不對業務產生影響。

b.支持事務的消息中間件

Apache開源的RocketMQ中間件能夠支持一種事務消息機制,確保本地操作和發送消息的異步處理達到本地事務的結果一致。

第一階段,RocketMQ在執行本地事務之前,會先發送一個Prepared消息,並且會持有這個消息的接口回查地址。

第二階段,執行本地事物操作。

第三階段,確認消息發送,通過第一階段拿到的接口地址URL執行回查,並修改狀態,如果本地事務成功,則修改狀態為已提交,否則修改狀態為已回滾。

其中,如果第三階段的確認消息發送失敗後,RocketMQ會有定時任務掃描集群中的事務消息,如果發現還是處於prepare狀態的消息,它會向消息發送者確認本地事務是否已執行成功。RocketMQ會根據發送端設置的策略來決定是回滾還是繼續發送確認消息。這樣就保證了消息的發送與本地事務同時成功或同時失敗。

再回到上面轉賬的例子,如果用戶A的賬戶餘額已經減少,且消息已經發送成功,作為消費者用戶B開始消費這條消息,這個時候就會出現消費失敗和消費超時兩個問題,解決超時問題的思路就是一直重試,直到消費端消費消息成功,整個過程中有可能會出現消息重複的問題,就需要採用前面說的冪等方案來進行處理。

分佈式事務—2PC協議

為了解決大型分佈式/微服務系統中的一致性問題,業界比較流行的做法是採用比較著名的有二階提交協議(2 Phase Commitment Protocol)和三階提交協議(3 PhaseCommitment Protocol)。考慮到性能問題,三階段提交協議目前較少被採用。本文也主要介紹二階段協議。

2PC協議

二階段提交協議是分佈式系統中較為經典的處理數據一致性的解決方案。在大型的集群環境中,對於單體微服務本身而言雖然能夠通過代碼質量、Mock測試等方法來確保自身服務的可用性,但是無法能夠保證其他服務的可用性。當一個全鏈路的端到端業務操作,常常會跨多個節點、多個應用,為了能夠保證全局事務的ACID特性,需要引入一個協調組件(這裡稱之為TM)來控制所有服務參與者(這裡稱之為RM)的操作結果,根據所有參與者的反饋結果來決定整個分佈式事務究竟是提交還是回滾的結果。

第一階段:稱為準備(prepare)階段。事務協調者向各個服務應用發送prepare請求,服務應用在得到請求後做預處理操作,預處理可能是做預檢查,也可能是把請求臨時存儲,可以理解為是一種試探性地提交。下面是一般的步驟:

a.事務協調者會問所有的參與者服務,是否可以提交操作。

b.各個參與者開始事務執行的準備工作:如資源上鎖,預留資源,寫回滾/重試的log。

c.參與者響應協調者,如果事務準備工作成功,則迴應“可以提交”,否則迴應拒絕提交。

第二階段:稱為提交(commit)/回滾(rollback)階段。是指事務真正提交或者回滾的階段。如果事務協調者發現事務參與者有一個在prepare階段出現失敗,則會要求所有的參與者進行回滾。如果協調者發現所有的參與者都prepare操作都是成功,那麼他將向所有的參與者發出提交請求,這時所有參與者才會正式提交。由此保證了要求全部提交成功,要麼全部失敗。下面是具體步驟:

a.如果所有的參與者都回應“可以提交”,那麼協調者向所有參與者發送“正式提交”的命令。參與者完成正式提交,並釋放所有資源,然後迴應“完成”,協調者收集各個服務的“完成”迴應後結束事務。

b.如果有一個參與者迴應“拒絕提交”,那麼協調者向所有的參與者發送“回滾操作”,並釋放所有的資源,然後迴應“回滾完成”,協調者收集各個服務應用的“回滾”返回後,取消整體的分佈式事務。

二階段提交協議解決的是分佈式系統/微服務架構中數據強一致性的問題,其原理簡單,但缺點也是存在,主要缺點如下:

a.單點問題:協調者在整個二階段中的作用非常重要,一旦部署協調者組件服務的節點出現不可用宕機情況,那麼會影響整個分佈式系統的正常運行。

b.同步阻塞:二階段提交執行過程中,所有服務參與者需要服從協調者的統一調度,期間處於阻塞狀態,會一定程度上影響整個系統的效率。

二、分佈式系統原理:

1. 哈希方式,把不同的值進行哈希運算,映射到,不同的機器或者節點。考慮冗餘的時候可以把多個哈希值映射到同一個地方。哈希的實現方式,取餘。其實現擴展時,比較困難,數據分散在很多機器上,擴展的時候要從個機器上獲取數據。而且容易出現分佈不均有的情況。

常見的哈希,用IP、URL、ID、或者固定的值進行哈希,總是得到相同的結果。

2. 按數據範圍分佈,比如ID在1~20的在機器A上,ID在21~40的在機器B上,ID在40~60的在機器C上實現,ID在60~100的分佈在機器D上,數據分佈比較均勻。如果某個節點處理能力有限,可以直接分裂該節點。維護數據分佈的元信息,可能出現單點瓶頸。幾千機器,每個機器又劃分為N個範圍,導致需要維護的數據分佈範圍元數據過大,導致可能需要幾臺機器實現。

一定要嚴格控制元數據量,進可能的減少元數據的存儲。

3. 按數據量分佈,另一類常用的數據分佈方式則是按照數據量分佈數據。與哈希方式和按數據範圍方式不同,數據量分佈數據與具體的數據特徵無關,而是將數據視為一個順序增長的文件,並將這個文件按照某一較為固定的大小劃分為若干數據塊(chunk),不同的數據塊分佈到不同的服務器上。與按數據範圍分佈數據的方式類似的是,按數據量分佈數據也需要記錄數據塊的具體分佈情況,並將該分佈信息作為元數據使用元數據服務器管理。

由於與具體的數據內容無關,按數據量分佈數據的方式一般沒有數據傾斜的問題,數據總是被均勻切分並分佈到集群中。當集群需要重新負載均衡時,只需通過遷移數據塊即可完成。集群擴容也沒有太大的限制,只需將部分數據庫遷移到新加入的機器上即可以完成擴容。按數據量劃分數據的缺點是需要管理較為複雜的元信息,與按範圍分佈數據的方式類似,當集群規模較大時,元信息的數據量也變得很大,高效的管理元信息成為新的課題。

4. 一致性哈希,構造哈希環,有哈希域[0,10],則構造3個部分,[1,4)/[4,9)/[9,10),[0,1)/分成了3個部分,這3部分是一個環狀,增加機器時,變動的是其附近的節點,分擔的是附近節點的壓力,其元數據的維護和按數據量分佈一樣。其未來的擴展,可以實現多個需節點。

5. 構建映射元數據,建立映射表的方式。

6. 副本與數據分佈,把一個數據副本分散到多臺服務器上。比如應用A的數據,存儲在A、B、C ,3臺機器上,如果3臺機器中,其中一臺出現問題,請求被處理到其他2臺機器上,如果加機器恢復,還需要從另外2臺機器上,Copy數據,又增加了這2臺機器的負擔。如果我們有應用A和應用B,各自有3臺機器,那麼我們可以把A應用分散在6臺機器上,B應用也分散在6臺機器上,可以實現相同的數據備份,但是應用存儲的數據被分散了。某臺機器損害,只是把該機器所承擔的負載平均分配到了,另外5臺機器上。恢復數據從5臺機器恢復,其速度快和給各臺服務器的壓力都不大,而且可以實現機器損害,更換完全不影響應用。

其原理是多個機器互為副本,是比較理想的實現負載分壓的方式。

7. 分佈式計算思想,移動數據不如移動計算,就進計算原則,減少跨進程、跨網絡、等跨度較大的實現,把計算所需的資源儘可能的靠近。因為可能出現網絡、遠程機器的瓶頸。

8. 常見分佈式系統數據分佈方式: GFS、HDFS:按數據量分佈;Map reduce 按GFS的數據分佈做本地化;BigTable、HBase按數據範圍分佈;Pnuts按哈希方式或者數據範圍分佈,可以選擇;Dynamo、Cassndra按一致性哈希;Mola、Armor、BigPipe按哈希方式分佈;Doris按哈希方式和按數據量分佈組合。

三、數據副本協議

1. 副本一定要滿足一定的可用性和一致性要求、具體容錯能力,即使出現一些問題也能提供可靠服務。

2. 數據副本的基本協議,中心化和去中心化2種基本的副本控制協議。

3. 中心化副本控制協議的基本思路是由一箇中心節點協調副本數據的更新、維護副本之間的一致性。中心化副本控制協議的優點是協議相對較為簡單,所有的副本相關的控制交由中心節點完成。併發控制將由中心節點完成,從而使得一個分佈式併發控制問題,簡化為一個單機併發控制問題。控制問題,簡化為一個單機併發控制問題。所謂併發控制,即多個節點同時需要修改副本數據時,需要解決“寫寫”、“讀寫”等併發衝突。單機系統上常用加鎖等方式進行併發控制。對於分佈式併發控制,加鎖也是一個常用的方法,但如果沒有中心節點統一進行鎖管理,就需要完全分佈式化的鎖系統,會使得協議非常複雜。中心化副本控制協議的缺點是系統的可用性依賴於中心化節點,當中心節點異常或與中心節點通信中斷時,系統將失去某些服務(通常至少失去更新服務),所以中心化副本控制協議的缺點正是存在一定的停服務時間。即存在單點問題,即使中心化節點是一個集群,也只不過是一個大的單點。

4. 副本數據同步常見問題,1)網絡異常,導致副本沒有得到數據;2)數據髒讀,主節點數據已經更新,但是由於某種原因,沒有得到最新數據;3)增加新節點沒有得到主節點數據,而讀數據時從新節點讀數據導致,沒有得到數據。

5. 去中心化副本控制協議沒有中心節點,協議中所有的節點都是完全對等的,節點之間通過平等協商達到一致。從而去中心化協議沒有因為中心化節點異常而帶來的停服務等問題。然而,沒有什麼事情是完美的,去中心化協議的最大的缺點是協議過程通常比較複雜。尤其當去中心化協議需要實現強一致性時,協議流程變得複雜且不容易理解。由於流程的複雜,去中心化協議的效率和性能較低。

6. Paxos是唯一在工程中得到應用的強一致性去中心化副本控制協議。ZooKeeper、Chubby,就是該協議的應用。

Zookeeper用Paxos協議選擇Leader,用Lease協議控制數據是否有效。用Quorum協議把Leader的數據同步到follow。

Zeekeeper,實現Quorum寫入時,如果沒有完全寫入成功,則所有的follow機器,反向向Leader寫數據,寫入數據後follow又向Leader同步數據,保持一致,如果是失敗的數據先寫入,你們follow同步到原來的數據,相對於回滾;如是是最新的數據先寫入Leader則就是完成了最新數據的更新。

7. Megastore,使用的是改進型行Paxos協議。

8. Dynamo / Cassandra使用基於一致性哈希的去中心化協議。Dynamo使用Quorum機制來管理副本。

9. Lease機制是最重要的分佈式協議,廣泛應用於各種實際的分佈式系統中。1)Lease通常定義為:頒發者在一定期限內給予持有者一定權利的協議。2)Lease 表達了頒發者在一定期限內的承諾,只要未過期頒發者必須嚴格遵守 lease 約定的承諾;3)Lease 的持有者在期限內使用頒發者的承諾,但 lease 一旦過期必須放棄使用或者重新和頒發者續約。4)的影響。中心服務器發出的lease的含義為:在lease的有效期內,中心服務器保證不會修改對應數據的值。5)可以通過版本號、過多上時間、或者到某個固定時間點認為Lease證書失效。

其原理和我們的Cache一樣,比如瀏覽器緩存道理一致。其要求時間時鐘同步,因為數據完全依賴於期限。

10. 心跳(heartbeat)檢測不可靠,假如檢測及其Q,被檢測機器A,可能由於Q發起檢測,但是A的迴應被阻塞,導致Q 認為A宕機,阻塞很快恢復,導致根據心跳檢測來做判斷不可靠;也可能是他們之間的網絡斷開;也可能是Q機器本身異常導致認為A機器宕機;如果根據Q的檢測結果,來判斷很可能出現多個主機的情況。

11. Write-all-read-one(簡稱WARO)是一種最簡單的副本控制規則,顧名思義即在更新時寫所有的副本,只有在所有的副本上更新成功,才認為更新成功,從而保證所有的副本一致,這樣在讀取數據時可以讀任一副本上的數據。寫多份,讀從其中一份讀取。

12. quorum協議,其實就是讀取成功的副本數大於失敗的副本數,你們讀取的副本里面一定包含了最新的副本。

13. Mola*和Armor*系統中所有的副本管理都是基於Quorum,即數據在多數副本上更新成功則認為成功。

14. Big Pipe*中的副本管理也是採用了WARO機制。

四、日誌技術

1. 日誌技術是宕機恢復的主要技術之一。日誌技術最初使用在數據庫系統中。嚴格來說日誌技術不是一種分佈式系統的技術,但在分佈式系統的實踐中,卻廣泛使用了日誌技術做宕機恢復,甚至如BigTable等系統將日誌保存到一個分佈式系統中進一步增強了系統容錯能力。

2. 兩種比較實用的日誌技術Redo Log與No Redo/No undo Log。

3. 數據庫的日誌主要分為Undo Log、Redo Log、Redo/Undo Log與No Redo/No Undo Log。這四類日誌的區別在更新日誌文件和數據文件的時間點要求不同,從而造成性能和效率也不相同。

4. 本節介紹另一種特殊的日誌技術“No Undo/No Redo log”,這種技術也稱之為“0/1目錄”(0/1 directory)。還有一個主記錄,記錄當前工作目錄,比如老數據在0目錄下,新數據在1目錄下,我們訪問數據時,通過主紀錄,記錄當前是工作在那個目錄下,如果是工作在目錄0下,取目錄0數據,反之取1目錄數據。

5. MySQL的主從庫設計也是基於日誌。從庫只需通過回放主庫的日誌,就可以實現與主庫的同步。由於從庫同步的速度與主庫更新的速度沒有強約束,這種方式只能實現最終一致性。

6. 在單機上,事務靠日誌技術或MVCC等技術實現。

7. 兩階段提交的思路比較簡單,在第一階段,協調者詢問所有的參與者是否可以提交事務(請參與者投票),所有參與者向協調者投票。在第二階段,協調者根據所有參與者的投票結果做出是否事務可以全局提交的決定,並通知所有的參與者執行該決定。在一個兩階段提交流程中,參與者不能改變自己的投票結果。兩階段提交協議的可以全局提交的前提是所有的參與者都同意提交事務,只要有一個參與者投票選擇放棄(abort)事務,則事務必須被放棄。可以這麼認為,兩階段提交協議對於這種超時的相關異常也沒有很好的容錯機制,整個流程只能阻塞在這裡,且對於參與者而言流程狀態處於未知,參與者即不能提交本地節點上的事務,也不能放棄本地節點事務。

8. 第一、兩階段提交協議的容錯能力較差。

9. 第二、兩階段提交協議的性能較差。一次成功的兩階段提交協議流程中,協調者與每個參與者之間至少需要兩輪交互4個消息“prepare”、“vote-commit”、“global-commit”、“確認global-commit”。過多的交互次數會降低性能。另一方面,協調者需要等待所有的參與者的投票結果,一旦存在較慢的參與者,會影響全局流程執行速度。

10. 顧名思義,MVCC即多個不同版本的數據實現併發控制的技術,其基本思想是為每次事務生成一個新版本的數據,在讀數據時選擇不同版本的數據即可以實現對事務結果的完整性讀取。在使用MVCC時,每個事務都是基於一個已生效的基礎版本進行更新,事務可以並行進行。其思想是根據版本號,在多個節點取同一個版本號的數據。

11. MVCC的流程過程非常類似於SVN等版本控制系統的流程,或者說SVN等版本控制系統就是使用的MVCC思想。

五、CAP理論

  1. CAP理論的定義很簡單,CAP三個字母分別代表了分佈式系統中三個相互矛盾的屬性:1)Consistency (一致性):CAP理論中的副本一致性特指強一致性(1.3.4 );

2)Availiablity(可用性):指系統在出現異常時已經可以提供服務;

3)Toleranceto the partition of network (分區容忍):指系統可以對網絡分區,這

種異常情況進行容錯處理。

2.CAP理論指出:無法設計一種分佈式協議,使得同時完全具備CAP三個屬性,即1)該種協議下的副本始終是強一致性,2)服務始終是可用的,3)協議可以容忍任何網絡分區異常;分佈式系統協議只能在CAP這三者間所有折中。

總結

以 上就是我對分佈式事務 ( DTS ) 及分佈式系統原理分析問題及其優化總結,分享給大家,希望大家可以瞭解什麼是分佈式事務 ( DTS ) 及分佈式系統原理分析問題及其優化。覺得收穫的話可以點個關注收藏轉發一波喔,謝謝大佬們支持!

1、多寫多敲代碼,好的代碼與紮實的基礎知識一定是實踐出來的

2、可以去百度搜索騰訊課堂圖靈學院的視頻來學習一下java架構實戰案例,還挺不錯的。

最後,每一位讀到這裡的網友,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序員的道路上,我們可以一起學習、一起進步。

3丶想了解學習以上課程內容可加群:469717771 驗證碼頭條(06 必過)

分佈式事務(DTS)及分佈式系統原理分析

相關推薦

推薦中...