國際開放標準組織定義了DTS(分佈式事務處理模型),模型中包含4種角色:應用程序,事務管理器,資源管理器和通訊資源管理器。 事務管理器是統管全局的管理者,資源管理器,通訊資源管理器是事務的參與者。算法
在JEE中定義了TX協議和XA協議,TX協議定義了應用程序與事務管理器直接的接口,XA協議定義事務管理器定義與資源管理器直接的接口。數據庫
下面咱們介紹的兩階段提交,三階段提交以及阿里提出的TCC都是根據DTS這一思想演變而來。緩存
1.兩階段提交協議。併發
2.三階段提交異步
3.TCC 分佈式
前面提到的兩階段和三階段提交協議,實際上他們能解決分佈式事務問題。可是遇到極端狀況是,系統會阻塞或者不一致的問題,須要運營或者技術人員解決。兩階段和三階段中都有不少參與者、多個階段實現一個事務,實現複雜,性能也是一個問題。在互聯網高併發系統中,鮮有使用兩階段,三階段的場景。高併發
後面有人提出了TCC協議,TCC就是將一個任務拆分紅Try、Confirm、Cancel三個步驟。正常的流程會先執行Try,若是執行沒有問題,則在執行Confirm,若是在執行過程當中出現了問題,則執行操做的逆操做Cancel。從正常的流程來說這也是一個兩階段提交,可是在執行出現問題的時候有必定的自我修復能力。若是任何參與者出現了問題,則協調者經過執行操做的逆操做來Cancle以前的操做。達到最終的一致性。性能
保持最終一致性的模式spa
在大規模、高併發服務化系統中,一個功能被拆分紅多個具備單一子功能的服務,一個流程會有多個系統的多個單一功能的服務組合實現,若是使用兩階段或者三階段提交協議,確實能解決系統間的一致性問題 。除了這兩個協議的自身問題,其實現也比較複雜、成本比價高。性能也很差.相比較而言,tcc協議更簡單而且更好實現。可是tcc協議因爲每一個事務都要執行try在執行confirm,略顯臃腫。所以,現實系統的底線是僅僅達到最重一致性。而不是實現專業的,複雜的一致性協議。實現最重一致性有一些很是有效,簡單的模式。下面就介紹這些模式的及其應用場景。接口
1.查詢模式
任何服務操做都提供一個查詢接口,用來向外部輸出操做執行的狀態。服務操做的適用方可經過查詢接口得知服務操做執行的狀態。爲了實現查詢,每次服務操做都要提供惟一的流水號標識。
2.補償模式
有了上面的查詢模式,在任何狀況下,咱們都能得知具體的操做所處的狀態,若是操做處於不正常的狀態。則須要處理操做中有問題的子操做。多是從新執行爲完成的子操做或者取消已完成的子操做。經過修復使得分佈式系統達到一致。
3.異步確保模式
異步確保模式是補償模式的一個典型案例,常常應用到使用方響應時間要求不過高的場景中,一般把這些類操做從主類中摘除,經過異步到方式進行處理,處理後把結果經過通知系統通知給使用方。這樣能夠對高併發進行削峯。如電商系統裏到物流,配送。
將要執行到異步操縱封裝入庫,而後經過定時任務撈取未完成到任務進行補償操做來實現異步取保機制。
4.按期校對模式
系統在沒有達到一致以前,系統見到狀態是不一致到,甚至是混亂的。須要經過補償操做來達到最終一致性。
在操做主流中的系統間執行校對操做,能夠在過後異步批量的校對操做的狀態。若是發現不一致的操做,則進行補償,補償操做與補償模式中的補償模式中的補償操做是同樣的。
另外,實現按期校對的一個關鍵就是分佈式系統中須要一個自始至終惟一的id,生產全局id通常有兩種方式。持久性:數據庫自增或者sequence 。時間性:通常由機器號,業務號,時間,節點內自增id。好比雪花算法。
全局id能夠將一個請求在分佈式系統中流轉路徑聚合,而調用連鏈中的spanid能夠將聚合的請求路徑經過樹形結構進行展現。可以快速定位問題,提升應急效率。
5.可靠消息模式
在分佈式系統中,對於主流程中優先級比較低的操做,大多采用異步的方式執行。也就是前面提到的異步確保模型。爲了充分的解耦,也因爲專業的消息隊列提供可伸縮,可分片,可持久化等功能,一般經過消息隊列實現異步化。對於消息隊列,咱們須要創建特殊的設施來保證可靠的消息發送及消息處理機的冥等性。
消息的可靠發送 消息發送以前將消息持久化到數據庫,狀態表示爲等待發送,而後發送消息,消息更改成發送成功。定時任務撈取一段時間後仍是待發送到消息,併發送消息。
處理到冥等性:存在消息發送到重試,就會可能出現重複消息。
保證操做的冥等性 的經常使用方法以下:
1.使用數據庫表的惟一鍵進行濾重,拒絕重複的請求
2.使用分佈式表對請求進行濾重。
3.使用狀態流轉的方向性濾重,一般使用數據庫的行級鎖來實現。
4.根據業務的特色,操做自己就是冥等的,例如:刪除一個資源,新增一個資源。
6.緩存一致性模型
在大規模,高併發系統中一個常見的核心需求就是億級的讀請求,顯然關係型數據庫並非解決高併發讀的最佳方案。
1 若是性能要求不是特別高,儘可能使用分佈式緩存。
2.寫緩存數據時必定要完整。
3.使用緩存犧牲了強一致性,爲了提升性能,數據庫與緩存只須要保證弱一致性
4.讀的順序時先讀緩存,後讀數據庫。寫的順序時先寫數據庫,後寫緩存。