在分佈式系統中,為了保證數據的高可用,通常,我們會將數據保留多個副本(replica),這些副本會放置在不同的物理的機器上。為了對用戶提供正確的 CRUD 等語義,我們需要保證這些放置在不同物理機器上的副本是一致的。分佈式事務在現在遍地都是分佈式部署的系統中幾乎是必要的。
我們先聊一下啥是事務?
分佈式事務、事務隔離級別、ACID我相信大家這些東西都耳熟能詳了,那什麼是事務呢?
概念:
一般是指要做的或所做的事情。
指作為單個邏輯工作單元執行的一系列操作,要麼全部執行,要麼全部不執行。
簡單的說,事務就是併發控制的單位,是用戶定義的一個操作序列。
特性:
事務是恢復和併發控制的基本單位。
事務應該具有4個屬性:原子性、一致性、隔離性、持久性。這四個屬性通常稱為ACID特性。
原子性(atomicity):一個事務是一個不可分割的工作單位,事務中包括的操作要麼都做,要麼都不做。
一致性(consistency):事務必須是使數據庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。
隔離性(isolation):一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對併發的其他事務是隔離的,併發執行的各個事務之間不能互相干擾。
持久性(durability):持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。
那什麼是分佈式事務呢?
這裡舉個簡單的例子:大家可以想一下,你下單流程可能涉及到10多個環節,你下單付錢都成功了,但是你優惠券扣減失敗了,積分新增失敗了,前者公司會被薅羊毛,後者用戶會不開心,
但是這些都在不同的服務怎麼保證大家都成功呢? 分佈式事務。
分佈式事務是指會涉及到操作多個數據庫的事務。其實就是將對同一庫事務的概念擴大到了對多個庫的事務。目的是為了保證分佈式系統中的數據一致性。分佈式事務處理的關鍵是必須有一種方法可以知道事務在任何地方所做的所有動作,提交或回滾事務的決定必須產生統一的結果(全部提交或全部回滾)
比較著名的分佈式事務有:
2pc(兩段式提交)
3pc(三段式提交)
TCC(Try、Confirm、Cancel)
半消息/最終一致性(RocketMQ)
這裡我就介紹下最簡單的2pc(兩段式),以及大家以後可能比較常用的半消息事務也就是最終一致性,別的事務都大同小異,都有很多優點。
當然也都有種種弊端:
例如長時間鎖定數據庫資源,導致系統的響應不快,併發上不去。
網絡抖動出現腦裂情況,導致事物參與者,不能很好地執行協調者的指令,導致數據不一致。
單點故障:例如事物協調者,在某一時刻宕機,雖然可以通過選舉機制產生新的Leader,但是這過程中,必然出現問題,而TCC,只有強悍的技術團隊,才能支持開發,成本太高。
開始介紹這個兩個事物吧。
![分佈式事務淺析及簡單實現](http://p2.ttnews.xyz/loading.gif)
2pc(兩段式提交) :
第一階段:準備階段(投票階段) 和第二階段:提交階段(執行階段)
2pc(兩段式提交)可以說是分佈式事務的最開始的樣子了,像極了媒婆,就是通過消息中間件或者全部事務管理來協調多個系統,在兩個系統操作事務的時候都鎖定資源但是不提交事務,等兩者都準備好了,告訴消息中間件或者全部事務管理者,然後再分別提交事務。不管最後結果如何,第二階段都會結束當前事務
但是問題所在是,如果A系統事務提交成功了,但是B系統在提交的時候網絡波動或者各種原因提交失敗了,其實還是會失敗的。
最終一致性:
![分佈式事務淺析及簡單實現](http://p2.ttnews.xyz/loading.gif)
整個流程中,我們能保證是:
業務主動方本地事務提交失敗,業務被動方不會收到消息的投遞。
只要業務主動方本地事務執行成功,那麼消息服務一定會投遞消息給下游的業務被動方,並最終保證業務被動方一定能成功消費該消息(消費成功或失敗,即最終一定會有一個最終態)。
不過呢技術就是這樣,各種極端的情況我們都需要考慮,也很難有完美的方案,所以才會有這麼多的方案三段式、TCC、最大努力通知等等分佈式事務方案,大家只需要知道為啥要做,做了有啥好處,有啥壞處,在實際開發的時候都注意下就好好了,系統都是根據業務場景設計出來的,離開業務的技術沒有意義,離開技術的業務沒有底氣。
閱讀更多 AiChinaTech 的文章