1. 程式人生 > >Akka-CQRS(0)- 基於akka-cluster的讀寫分離框架,構建gRPC移動應用後端架構

Akka-CQRS(0)- 基於akka-cluster的讀寫分離框架,構建gRPC移動應用後端架構

異常 在線 persist 體系 分片 系統性能 resp 數據庫更新 讀寫分離

上一篇我們討論了akka-cluster的分片(sharding)技術。在提供的例子中感覺到akka這樣的分布式系統工具特別適合支持大量的帶有內置狀態的,相對獨立完整的程序在集群節點上分布運算。這裏重點要關註這些程序的內部狀態,它們會占用系統資源包括內存。把狀態保存在內存裏相對存放在數據庫裏能顯著提高程序運算效率。在系統出現各種情況下對這些非持久化的程序狀態的管理自然就成為了需要考慮的問題,此其一。在一個多用戶、高並發的大型分布式系統裏往往數據庫數據使用會產生大量的沖突影響系統性能。如果能夠把數據庫的寫入和讀取分成互不關聯的操作就可以避免很多資源占用的沖突。

CQRS(Command Query Responsibility Segregation 讀寫責任分離)就是解決讀寫分離問題的一個很好的框架。CQRS實際上應該是一種大量數據並發錄入的解決方案。通過讀寫分離降低數據錄入過程對系統響應的影響。

akka-CQRS大約是由event-sourcing、persistenceActor、persistenceQuery三個部分組成。event-sourcing+persistenceActor是一種數據庫存寫模式。傳統數據庫的數據更新一般直接更改數據表裏的數據值。而event-sourcing模式是把所有更該數據的事件(events)或者說是動作都存放在一個log(journal)表裏。如果把這個journal表裏的所有記錄都重新演算一下,任何時間都可以得出數據庫表裏當前的狀態值。當然,這個journal表可能會存放大量的數據,但在大數據時代的分布式系統裏這也算不了什麽。由於journal表的寫入永遠是從後附加的,是一種不可變模式(immutable),所以效率很高,可以支持大數據表的寫入。再就是journal表裏記錄的事件是嚴格按發生時間順序的,所以在重新運算更新狀態時發生沖突機會甚微,而且一旦真的發生異常還可以再重新演算journal裏的記錄恢復正確的狀態。

persistenceQuery則是一套與事件存寫完全分離代表CQRS Q的讀取部分,主要工作是定時按批量從journal裏讀取記錄再把event還原成為數據庫更新語句然後對系統業務數據庫進行更新。而業務應用軟件的數據操作,如業務查詢、處理、分析等都是針對業務數據庫的。

最近在考慮搞一套主要以移動設備為業務工具的信息系統框架。由於移動OS相對功能較弱,加上編程困難等,最好只負責應用的前端錄入和表達部分。所有業務邏輯就只能放在後端了。打比方說如果開發一套基於android的POS收銀系統,所有收銀操作指令都在後端執行,然後向前端返回結果。這樣的POS前端只負責采集指令輸入然後顯示後端處理結果。根據上篇對akka-cluster-sharding應用場景分析,我們可以用一個分片shard來負責一臺POS機後端。考慮到akka-cluster集群分布式運算可擴展能力特性,處理萬級POS同時在線應該不成問題。當然,每個POS開單銷售的過程都存放在內存作為每單銷售的狀態。這種資源分享的模式恰恰是akka-cluster-sharding的強項。剩下海量並發的數據庫操作,就可以通過akka-CQRS框架來應對了。

另外,由於移動前端和後臺系統都是企業內部應用系統,可以用gRPC模式替代傳統主流的HTTP/1.0協議作為系統主要集成方式。gRPC方式是基於HTTP/2.0協議上的,可以實現點對點的持續連接,支持雙向數據流操作,有效解決了request/response模式帶來的效率問題。我們在前面的博客裏已經構建了基於gRPC,多分布式數據庫的數據流編程框架,可以直接采用。google的移動應用編程語言dart2也是支持gRPC的,從整體系統實現的可行性方面應該不會有什麽問題了。

在下面跟著的幾篇博客裏我們會分別討論event-sourcing,persistenceActor,persistenceQuery和gRPC。

Akka-CQRS(0)- 基於akka-cluster的讀寫分離框架,構建gRPC移動應用後端架構