系統軟件為了實現一定的業務,會將現實中的人、事、物進行抽象表示,并將其映射為系統中的模型。
業務模型大致可以按以下來構建:
1、定義系統中應該存在哪些實體、實體上有哪些屬性。
2、定義實體之間的各種拓撲關系,如從屬、嵌套、多對多。
3、定義實體和屬性的動態關系,即定義系統流程
第1、2步是靜態的,因此可以用E-R圖(實體-關系圖)來表示,它能夠描述系統在某個時間節點所有可能的狀態,第3步需要用流程圖和“狀態-轉移圖”來表示,它能夠描述系統隨著時間的推移的變化規律。
業務模型是系統中最容易發生變化的部分,體現在:
1、系統中的實體、屬性種類的增減
2、實體之間拓撲關系的改變
3、系統流程變更
數據庫是負責存儲這些業務模型的。數據存儲模型的設計就是數據庫的設計,工作包括:數據存儲結構、索引結構、讀寫控制。實體對應到表、實體的屬性對應到表中的字段,遵循數據庫設計范式減少冗余的表和字段。
單體應用時代通常采用單一的關系數據庫,微服務時代并不再受限于單一數據庫,微服務架構下,服務可以選擇專精于相應領域中的數據庫,如搜索引擎數據庫Elasticsearch,分布式存取海量數據的MongoDB等。
軟件系統為了保證業務模型上的狀態的互斥完備,就要求存儲模型也是互斥完備的。從數據庫角度來看,就是數據庫中某些表中的字段必須同時變化;從數據庫客戶端來看就是對數據庫進行一組寫入操作,要么成功,要么失敗。這就是所謂的事務。
事務的特點ACID:
1、A(Atomicity)原子性,在同一組數據庫操作中,其中某一步失敗了,之前的所有操作都會被回滾,不允許出現部分成功,部分失敗的情況。
2、C(Consistency)一致性,即數據操作符合某種業務約束。比如說A賬戶轉錢給B賬戶,那么對于兩個賬戶的錢的增減,應該符合A賬戶錢會減少,B賬戶應該增多。這就是一個比較簡單轉賬業務邏輯。符合相應的業務邏輯就達到了一致性要求。
3、I(Isolation)隔離性,并發的數據操作要有一定的隔離性,隔離性最差的情況是并發操作沒有一點隔離、互相干擾;最好的情況是并發操作等效于一系列串行操作。隔離性越高也意味著數據庫需要更多的資源來實現,存取數據的吞吐量也會隨之降低、延遲增加。
4、D(Durability)持久性,要求到達數據庫的數據不會丟失,換據話說就是存儲到了外存中,計算機停電、重啟等條件都不會導致數據丟失。
分布式系統的出現,尤其是分布式數據庫,相比較于單體應用和傳統的數據庫來說,除了要滿足ACID標準事務上,分布式系統還有一個問題尚未等到解決。就是常說的CAP三選二定理。
1、C(Consistency):一致性,就是說分布式系統的任何節點對同一個Key的讀寫請求的結果都是完全一致的。
2、A(Availability):可用性,就是每次請求都能夠得到及時并正常的響應,但是不保證數據是最新的。
3、P(Partition tolerance)分區容錯性,節點不能連通時,不能保持正常的運轉。
這三個特性不能同時滿足,只能滿足其中兩個。
有人是這么說的,因為P分區容錯性通常是無法避免的既定事實,如果不存在網絡分隔,又或者說不要求在出網絡隔離時,仍然要正常提供服務,那么對于這種情況完全可以放棄分布式架構,直接用集中心架構來做就可以。所以現在變成了,接受P,在C和A之間根據業務需要進行選擇。
1、選擇C一致性,放棄A可用性,就是要強一致性,低可用性。在這類系統中,寫入數據庫的請求只在提交并且同步到所有的數據庫節點后才會返回響應,任意一個節點出現故障都會導致服務整體不可用,直至故障修復。賬務金融領域的系統通常會采用這種架構。
2、選擇A可用性,放棄C一致性,就是要高可用,最終一致性。在這類系統中,寫入數據庫的請求只要在部分數據庫節點上成功提交即可立即返回響應,不需要等到數據同步到所有數據庫節點才返回。使用這樣的架構可以提供服務的可用率,只有要少數據存活的服務節點,服務就可用。壞處是寫入數據請求完成后的一段時間(無上限)內,讀取同一條數據的結果可能會有一定的概率是錯誤的,這種數據約束稱為BASE(Basically Available Soft state Eventually consistent)。
(1)基本可用:通過使用分布式數據庫,盡可能使用讀寫操作處于可用的狀態,但不保證數據的一致性,如數據可能沒有被持久化、或讀回的數據不是最新的。
(2)軟狀態:即某條數據在寫入后一段時間內的狀態是未知的,在最終收斂之前,系統有一定概率會返回最新的值。
(3)最終一致性:在系統功能正常的前提下,等待足夠長的時間之后,某條數據在系統中的狀態能夠收斂達成一致,之后,讀取到的數據都是最新的。
如果分布式系統如果采用了分布式甚至是異構的數據存儲方案,那么在寫順序方向可能會遇到問題: 同一條數據在不同服務上并發寫入時,可能會因為寫入順序不同而導致寫入的數據不一致。這種問題并不一定違反了BASE或ACID約束,但前業務模型的角度來看,這不是預期的結果,系統不能正確反映業務模型。比如說現在A、B、C三個服務各自使用了不同的數據庫,現在有兩個請求1和請求2,并發修改同一個數據項,這個數據項分別由這三個服務進行處理,由于網絡延遲,這個數據項在三個數據庫中的值可能會不一致,如在A中為100,在C中為200.
現在業界已有一些分布式事件框架方案:
1、XA標準和二階段提交協議
XA標準(eXtended Architecture 擴展后的架構)這個標準目的是嘗試提供一套分布式事務的處理的標準。它描述了全局的事務管理與局部的資源管理器之間的接口。通過這套接口,應用可以在同一事務中跨越多個服務訪問多個資源(如數據庫、隊列、服務)。這個標準使用了兩階段提交協議(two-phase commit,2PC)來保證所有資源同時提交或回滾任何特定的事務。
兩階段提交協議引入協調者角色,它負責統一掌握所有數據存儲節點(參與者)的操作結果:
第一階段:參與者并發進行數據操作,將結果是否成功通知協調者;
第二階段:協調者根據所有參與者的反饋,決定是確認提交還是中止操作,并將這個決定告知所有參與者。
XA標準和二階段提交協議的好處是:強一致性,實現數據在多個數據庫上的ACID約束;業務侵入性也小,完全依賴各個數據庫本身劫持實現分布式事務,不需要修改業務邏輯。壞處是:數據庫的選型受限,只能選擇支持XA標準的數據庫;其次就是單點故障降低可用性,所有節點都不能出錯;支持XA標準的數據庫在設計上有大量的阻塞和資源占位,數據體量和吞吐量擴展性差。
總結來說XA標準和二階段提交協議是強一致性,低可用性的方案,正好是金融行業常用的架構。
2、Saga分布式事務框架
它的思路是借助驅動流程機制,按順序執行每個數據操作步驟。一旦出錯,就倒序執行之前各步驟對應的“補償”操作。所以Saga要求每個步驟涉及的服務都要提供正向操作接口和對應的補償操作接口。
Saga框架通過對一些基礎服務進行組合/編排來完成各種業務需求,比較靈活,對數據庫也沒有什么特別的要求,甚至不要數據庫。它只滿足了ACID中的A和C。需要服務實現數據補償的操作,這工作會增加開發和維護的成本。
Saga目前有Saga Orchestration 和Choreography兩種實現。
3、ACID事務鏈的分布式事務框架
ACID事務鏈要求參與分布式事務的所有服務都要使用支持ACID事務的數據庫,在每個服務內部,都將數據操作和同步調用相鄰服務的操作打包到一個ACID事件中,通過ACID事務的鏈式調用來實現分布式事務。它的優點相當明顯就是支持ACID。回滾的操作由支持ACID數據庫執行。缺點也明顯數據庫選型受限,服務耦合過多,服務之間的依賴是鏈式拓撲,非常不方便調整,如果出現服務之間的循環依賴,會出現很多麻煩。