DDD-CQRS的落地案例

摘要

在以前的文章DDD-CQRS能解什麼問題中,闡述了什麼是CQRS。可是並無業務需求能夠應用CQRS。最近須要處理一個文本增量更新的業務,通過需求分析後,嘗試使用CQRS來解這個問題安全

問題分析

一個文本頁面編輯,對象很大,以前是全量保存。涉及到的網絡傳輸對象比較大,常常超時OOM,因此交互改爲,只保存修改的部分,也就是增量更新。網絡

以前業務中無法使用CQRS,在於使用CQRS後,數據的維護變得異常麻煩。好比我對一個表單進行了反覆修改,生成了N份歷史修改數據,獲取最新數據時須要對這些歷史數據進行合併,變得異常麻煩。
此次業務可以使用在於,架構

  1. 拆分寫,可以有效的減小數據傳輸。
  2. 讀寫能夠分離,分別擴展
  3. 經過事件溯源,能夠恢復數據到任意編輯的版本

具體設計

系統總體採用CQRS+Event-Sourcing來實現框架

CQRS微服務

CQRS模式經過使用不一樣的接口來分離讀取數據和更新數據的操做。CQRS模式能夠最大化性能,擴展性以及安全性,
還會爲系統的持續演化提供更多的彈性,防止Update命令在域模型Level發生衝突。性能

文本編輯這塊領域模型很薄,沒有什麼領域校驗與約束,按讀取數據/更新數據分離,當讀寫壓力不一樣時,之後能夠拆分紅不一樣的服務,分別擴展。.net

Event Sourcing(事件溯源)設計

a.不保存對象的最新狀態,而是保存對象產生的全部事件
b.經過事件溯源(Event Sourcing,ES)獲得對象最新狀態;3d

系統總體分爲三大部分對象

一. command

全部數據修改命令,更新Command、撤銷Command、覆蓋Command
會持久化存儲到CommitRepository中。而後發出事件消息

二. event-handle

對於文本編輯這個case,事件處理主要是合併提交的command event。不然事件溯源時,須要處理的數據更新事件太多,耗時太長。

三. query

查詢數據,可以根據修改記錄獲取任意commit的數據。

三大部分分離,能夠部署爲單個服務,也能夠解耦爲多個服務,便於擴展。

須要解決的問題

  1. 如何保證事件的有序性

CQRS的一個典型問題就是生產端的事件順序和消費端的事件順序不一致,致使數據不一致的問題。如何去解決呢?

Command處理部分處理全部的數據更新部分,會生成一個全局有序的commitid,表明着更新的順序。也就是生產端的事件順序,可是到達咱們消費端的順序卻不必定是這個順序。因此消費端,事件處理完成後,會更新消費的最新commitid。若是當前事件的commitid小於最新的commitid,事件遺棄。

  1. 如何保證讀數據性能
    event handle部分會去合併commit,因此讀數據不是從全部的修改數據commit中合併數據。數據已經預先處理了,因此會大大加快讀取效率,能夠控制待合併的數據在5~10commits範圍以內。

  2. 數據會丟失嗎

系統分離後,沒有事務保證,數據的完整性如何保證。

當數據更新Command寫入成功後,表明這條數據更新成功,這個數據就不會丟失。由於這些數據都已經被持久化了,剩下的問題就是讀取這些提交的Command Commit。咱們能夠經過合併這些commit,獲得最新的完整數據。因此即便event-handle部分宕機了,仍然能夠讀取到最新的數據。

說明

這個案例仍是沒有應用框架,調研過axon,評估目前還不是太適合用,代碼可讀性不強,帶來的好處不明顯。後續再考慮是否須要引入框架。

DDD系列

咱們團隊是如何落地DDD的(1)

可落地的DDD的(2)-爲何說MVC工程架構已通過時

可落地的DDD(3)-如何利用DDD進行微服務的劃分

可落地的DDD(4)-如何利用DDD進行微服務的劃分(2)

可落地的DDD(5)-戰術設計

如何避免寫出爛的業務代碼(1)-領域對象與領域服務

如何避免寫出爛的業務代碼(2) DDD整改

DDD-CQRS能解什麼問題

一次關於聚合根的激烈討論

相關文章
相關標籤/搜索