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

雪川大蟲發表於2019-01-22

   上一篇我們討論了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。

相關文章