分散式事務與CAP理論淺談
微服務系統所設計的系統是分散式系統。分散式系統有一個著名的CAP理論,即同時滿足“一致性”“可用性”和“分割槽容錯”是一件不可能的事。CAP理論是由Eric Brewer在2000年PODC會議上提出的,該理論在兩年後被證明成立。CAP理論告訴架構師不要妄想設計出同時滿足三者的系統,應該有所取捨,設計出適合業務的系統。CAP理論示意圖
- Consistency:指資料的強一致性。如果寫入某個資料成功,之後讀取,讀到的都是新寫入的資料;如果寫入失敗,之後讀取的都不是寫入失敗的資料。
- Availability:指服務的可用性。
- Partition-tolerance:指分割槽容錯。
在分散式系統中,P是基本要求,而單體服務是CA系統。微服務系統通常是一個AP系統,即同時滿足了可用性和分割槽容錯。這就有了一個難題:在分散式系統中如何保證資料的一致性?這就是大家經常討論的分散式事務。
在微服務系統中,每個服務都是獨立的程序單元,每個服務都有自己的資料庫。通常情況下,只有關係型資料庫在特定的資料引擎下才支援事務,而大多數非關係型資料庫是不支援事務的,例如 MongDB 是不支援事務的,而 Redis 是支援事務的。在微服務架構中,分散式事務一直都是一個難以解決的問題,業界給出的解決辦法通常是兩階段提交。
網上購物在日常生活中是一個非常普通的場景,假設我在淘寶上購買了一部手機,需要從我的賬戶中扣除1000元錢,同時手機的庫存數量需要減1。當然需要在賣方的賬戶中加1000元錢,為了使案例簡化,暫時不用考慮。
如果這是一個單體應用,並且使用支援事務的MySQL資料庫(InnoDB資料庫引擎才支援事務),我們可能這樣寫程式碼:
@Transactional
public void updata() throws RuntimeException{
updateAccountTable(); //更新賬戶表
updateGoodsTable(); //更新商品表
}
如果是微服務架構,賬戶是一個服務,而商品是一個服務,這時不能用資料庫自帶的事務,因為這兩個資料表不在一個數據庫中。因此常常用到兩階段提交,兩階段提交的過程如圖所示
第一階段,service-account 發起一個分散式事務,交給事務協調器TC處理,事務協調器TC向所有參與的事務的節點發送處理事務操作的準備操作。所有的參與節點執行準備操作,將 Undo 和 Redo 資訊寫進日誌,並向事務管理器返回準備操作是否成功。
第二階段,事務管理器收集所有節點的準備操作是否成功,如果都成功,則通知所有的節點執行提交操作;如果有一個失敗,則執行回滾操作。
兩階段提交,將事務分成兩部分能夠大大提高分散式事務成功的概率。如果在第一階段都成功了,而執行第二階段的某一節點失敗,仍然導致資料的不準確,這時一般需要人工去處理,這就是當初在第一步記錄日誌的原因。另外,如果分散式事務涉及的節點很多,某一個節點的網路出現異常會導致整個事務處於阻塞狀態,大大降低資料庫的效能。所以一般情況下,儘量少用分散式事務。
本文參考自《深入理解Spring Cloud與微服務構建》方誌朋