分佈式事務講解

                                                                                            


說明:由於2015年10月18號  由朋友龔正組織的技術交流會討論的分佈式事務,故而整理一下,加上自己理解寫的

單機事務講解

分佈式事務的講解(並說出常見的分佈式事務的模型)

 

一.什麼是事務
事務是應用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,一個事務中的一系列的操作要麼全部成功,要麼一個都不做。
事務的結束有兩種,當事務中的所以步驟全部成功執行時,事務提交。如果其中一個步驟失敗,將發生回滾操作,撤消撤消之前到事務開始時的所以操作。

 

事務的基本屬性 ACID
事務具有四個特徵:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和永久性( Durability  )。這四個特性簡稱爲 ACID 特性。

1 、原子性
事務是數據庫的邏輯工作單位,事務中包含的各操作要麼都做,要麼都不做
2 、一致性
事 務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。因此當數據庫只包含成功事務提交的結果時,就說數據庫處於一致性狀態。如果數據庫系統 運行中發生故障,有些事務尚未完成就被迫中斷,這些未完成事務對數據庫所做的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是 不一致的狀態。
3 、隔離性
一個事務的執行不能其它事務干擾。即一個事務內部的操作及使用的數據對其它併發事務是隔離的,併發執行的各個事務之間不能互相干擾。
4 、永久性
也稱永久性,指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。


數據庫事務隔離級別

數據庫事務的隔離級別有4個,由低到高依次爲Read uncommitted、Read committed、Repeatable read、Serializable,這四個級別可以逐個解決髒讀、不可重複讀、幻讀這幾類問題。

注意:我們討論隔離級別的場景,主要是在多個事務併發的情況下,因此,接下來的講解都圍繞事務併發。

Read uncommitted 讀未提交

公司發工資了,領導把5000元打到singo的賬號上,但是該事務並未提交,而 singo正好去查看賬戶,發現工資已經到賬,是5000元整,非常高興。可是不幸的是,領導發現發給singo的工資金額不對,是2000元,於是迅速 回滾了事務,修改金額後,將事務提交,最後singo實際的工資只有2000元,singo空歡喜一場。




出現上述情況,即我們所說的髒讀,兩個併發的事務,“事務A:領導給singo發工資”、“事務B:singo查詢工資賬戶”,事務B讀取了事務A尚未提交的數據。

當隔離級別設置爲Read uncommitted時,就可能出現髒讀,如何避免髒讀,請看下一個隔離級別。

Readcommitted 讀提交

singo拿着工資卡去消費,系統讀取到卡里確實有2000元,而此時她的老婆也正好在網上轉賬,把singo工資卡的2000元轉到另一賬戶,並在singo之前提交了事務,當singo扣款時,系統檢查到singo的工資卡已經沒有 錢,扣款失敗,singo十分納悶,明明卡里有錢,爲何......

出現上述情況,即我們所說的不可重複讀,兩個併發的事務,“事務A:singo消費”、“事務B:singo的老婆網上轉賬”,事務A事先讀取了數據,事務B緊接了更新了數據,並提交了事務,而事務A再次讀取該數據時,數據已經發生了改變。

當隔離級別設置爲Read committed時,避免了髒讀,但是可能會造成不可重複讀。

大多數數據庫的默認級別就是Readcommitted,比如Sql Server , Oracle。如何解決不可重複讀這一問題,請看下一個隔離級別。

 

簡單說:就是事務A和事務B都能看到當前數據狀態,只是看那個事務先提交,另一個事務的操作是在已提交事務的基礎上再操作的

 

Repeatableread 重複讀

當隔離級別設置爲Repeatable read時,可以避免不可重複讀。當singo拿着工資卡去消費時,一旦系統開始讀取工資卡信息(即事務開始),singo的老婆就不可能對該記錄進行修改,也就是singo的老婆不能在此時轉賬。

雖然Repeatable read避免了不可重複讀,但還有可能出現幻讀。

singo的老婆工作在銀行部門,她時常通過銀行內部系統查看singo的信用卡消費記錄。有一天,她正在查詢到singo當月信用卡的總消費金額(selectsum(amount) from transaction where month = 本月)爲80元,而singo此時正好在外面胡吃海塞後在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄(insert transaction ... ),並提交了事務,隨後singo的老婆將singo當月信用卡消費的明細打印到A4紙上,卻發現消費總額爲1080元,singo的老婆很詫異,以爲出現了幻覺,幻讀就這樣產生了。

 

簡單說 :就是事務A看不到事務B對數據的修改,事務A查看的還是事務B之前的數據

注:Mysql的默認隔離級別就是Repeatable read。

Serializable序列化(通常也叫串讀)

Serializable是最高的事務隔離級別,同時代價也花費最高,性能很低,一般很少使用,在該級別下,事務順序執行,不僅可以避免髒讀、不可重複讀,還避免了幻像讀。

 

最後剩下一個事務的傳播行爲,網址:http://blog.csdn.net/loadhai/article/details/17800537

 

 

1.  單機事務:

舉例:支付寶向餘額寶轉賬100元  假如是在一臺服務器上進行  涉及到的操作是:

鎖住賬戶A的支付寶   鎖住賬戶A的餘額寶  查詢賬戶A的支付寶是否足夠100元    支付寶更新   餘額寶更新   提交事務

在單機中非常簡單,只要滿足事務的基特性即可,現實中支付寶和餘額寶是兩個應用,也有幾個億的用,不可能只在一臺服務器上,這就出現了服務器集羣,支付寶是一個應用,餘額

寶是一個應用,這才符合實際,那當前事務拆解:


現在怎麼保證兩個事務同時完成,同時失敗呢?也就是怎麼保持事務ACID呢?

 

A.先說下兩段提交協議2PC(2 Phase Commit)模型,這是一般情況下分佈式事務處理模型


準備階段:事務管理器通知支付寶事務和餘額寶事務,你們可以執行事務了,此時支付寶和餘額寶事務開始準備所有相關工作和處理,完事後給TM一個準備就緒消息。

提交階段:

所有事務都準備OK後,TM發送提交(或取消)消息,相關子事務開始處理本事務

借宿階段:

TM釋放相關資源,分佈式事務結束

 

 

說明:分佈式事務無法保證事務的一致性,但能保證弱一致性,就是最終一致性

反觀此種做法,弊端:1.資源消耗大  2.會有宕機情況的發生  此時主要根據日誌恢復未完成的事務

 

有一種說法 :最好的分佈式事務,就是不用分佈式事務,就是單機事務,上述業務能否不用2PC這種分佈式事務的處理方法呢,因爲幾個億的數據量,你都給鎖住,在加上TM,那是驚人的消耗內存資源,相當於頁面要等待很久的反應,支付寶餘額寶會用麼?顯然不會

 

B.較第一種做法,另一種做法事務MQ (消息機制)

MQ是 一個消息隊列  在實際生產環境中也是一個集羣(更深也伴有自己的數據庫,也有狀態機)

 

 

此機制爲:支付寶事務 在開始 向MQ發送一條消息,我開始了,在完成後在發一條消息,我完成了,此時,MQ收到後會通知餘額寶事務去完成事務

 

ACK 代表: 確實 好 我知道了

 

在此機制中,大家想想 支付寶若只在開始發送消息會出現什麼問題?只在最後發送消息會出現什麼問題?此機制最大的弊端在哪?

 

只在開始發送, 可能支付寶事務會失敗,但餘額寶成功了;只在最後發,可能支付寶事務成功,但餘額寶時報了

 

 

這邊全是理論知識,在實際中,我沒用過,忘大家提出問題,一起進步,謝謝





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章