2015-10-22 23 views
15

事件採購和CQRS是偉大的,因爲它會趕走被卡住它的開發者一起工作的應用程序的生命週期,除非有一個大的數據遷移項目一個預建模的數據庫開發人員。 CQRS和ES還具有擴展事件存儲,審計日誌等已經遍佈互聯網的其他好處。使用Event sourcing和CQRS的缺點是什麼?

但是,什麼缺點呢?

這裏是我能想到的研究和寫作小的演示應用程式後

  1. 複雜一些缺點:有人說ES是複雜的。但我認爲有一個複雜的應用程序比複雜的數據庫模型更好,在這個模型上只能使用查詢語言(多個連接,索引等)運行非常有限的查詢。我的意思是像Scala這樣的編程語言有非常豐富的集合庫,它非常靈活地生成一些嚴重複雜的聚合,並且還有Apache Spark,這使得它可以輕鬆查詢分佈式集合。但數據庫將始終受限於查詢語言功能,而分佈式數據庫更難以分發應用程序代碼(只需在另一臺機器上部署另一個實例!)
  2. 高磁盤空間使用情況:事件商店可能最終使用大量的磁盤空間來存儲事件。但是我們可以每隔幾周安排一次清理工作並創建快照,也可能是我們可以在外部HD上本地存儲歷史事件,只是因爲我們將來需要舊事件?
  3. 內存佔用率過高:每個領域對象的狀態存儲在存儲器中這可能會增加內存的使用,我們都RAM是多麼昂貴。 大問題!,因爲我很窮!任何解決方案?可能會使用Sqlite而不是在內存中存儲狀態?我通過在應用程序中引入多個Sqlite實例來使事情更復雜嗎?
  4. 較長的啓動時間:失敗或軟件升級啓動速度較慢,具體取決於事件數量。但是我們可以使用快照來解決這個問題?
  5. 最終一致性:問題對於某些應用。想象一下,如果Facebook使用CQRS的事件採購來存儲帖子,並考慮Facebook的系統有多忙,並且如果我發佈了一篇文章,我會在第二天看到我的FB帖子:)
  6. Event store中的序列化事件:Event stores store events作爲序列化對象,這意味着無論如何我們都無法查詢事件存儲中的事件內容。我們將來無法再爲該活動添加其他屬性。解決方案是將事件存儲爲JSON對象而不是序列化事件?但這是個好主意嗎?或者添加更多的事件來支持對orignal事件對象的更改?

可有人請我上帶來了這裏的缺點意見,並糾正我,如果我錯了,並建議其他任何我可能已經錯過了?

+2

爲什麼每個域對象的狀態都存儲在內存中?當需要時,域對象將從事件中重新創建。爲什麼你認爲FB不會使用事件採購,只是因爲他們很忙?我的理解是,他們使用單個寫入主機和幾個同步「最終」的讀取從機,所以他們確實使用最終的一致性,這就是爲什麼有時您可以發佈某些內容,然後在Feed中看不到它。 –

+0

有道理!但我認爲域對象的狀態將被存儲在內存中的原因是因爲它們的重新創建非常昂貴。每次有該域對象的1個屬性更新時,是否真的推動每個域對象有數千個事件?我想我對FB沒有使用事件採購是錯誤的。謝謝:) – hajime

+1

通常你不會有每個對象有數千個事件,但是如果你這麼做的話可能不如你想像的那麼慢(簡單的選擇,沒有連接來獲取事件),然後應用在內存中。如果在進行性能測試時確實證明這是一個問題,則可以始終爲對象「快照」事件。 –

回答

23

這是我對此的看法。

  1. CQRS + ES可以通過具有豐富的域對象,簡單的數據模型,歷史跟蹤,更深入地併發問題,可擴展性和更使事情複雜軟件系統簡單得多。它需要以不同的方式思考系統,因此可能難以找到合格的開發人員。但是CQRS可以更簡單地將開發人員的職責分開。例如,初級開發人員可以純粹使用讀取方而不必觸摸業務邏輯。

  2. 數據副本肯定需要更多磁盤空間。但是現在存儲相對便宜。它可能需要IT支持團隊進行更多備份,並計劃在出現​​問題時如何恢復系統。但是,現在的服務器虛擬化使其更加簡化了工作流程。而且,在沒有單一數據庫的情況下,在系統中創建冗餘容易得多。

  3. 我不認爲更高的內存使用率是一個問題。業務對象水合應該按需完成。對象不應該保留對已經被保存的事件的引用。只有持續數據時纔會發生事件補水。在讀取方面,您沒有通常在分層系統中發生的實體 - > DTO - > ViewModel轉換,並且您不會有任何種類的對象更改跟蹤全功能ORM通常會執行的操作。大多數系統執行的讀取次數遠多於寫入次數

  4. 如果由於各種數據上下文的初始化而使用多個異構數據庫,較長的啓動時間可能會是一個小問題。但是,如果您正在使用ADO .NET這樣的簡單事件與事件存儲和讀取方的micro-ORM進行交互,則系統將比任何全功能ORM「冷啓動」更快。這裏重要的事情不是讓您訪問數據的方式過於複雜。這實際上是CQRS應該解決的一個問題。正如我之前所說的,讀取側應該爲視圖建模,並且不會有任何重新映射數據的開銷。

  5. 根據我的經驗,兩階段提交可以很好地適用於無需根據數千用戶進行擴展的系統。您需要選擇適用於分佈式事務協調器的數據庫。例如,PostgreSQL可以很好地讀寫單獨的模型。如果系統需要針對大量的併發用戶進行擴展,則必須考慮到最終的一致性。在某些情況下,您可能會聚合根或上下文邊界,而這些邊界不使用CQRS來避免最終的一致性。這對於域的非協作部分是有意義的。

  6. 如果您爲事件存儲選擇正確的數據庫,則可以按照JSON或XML等格式查詢事件。這應該只是爲了分析的目的。系統內部沒有任何內容可以通過聚合根ID和事件類型以外的任何其他信息查詢事件存儲。該數據將被編入索引,並在序列化事件之外生存。

+0

感謝您的詳細解答。這使我對事情變得更加清楚。 – hajime

+0

我只是想補充一點5.我們應該避免兩個階段的提交。最好的解決方案是始終訂閱事件存儲並儘可能進行處理,但不能將事件存儲與分佈式事務綁定 – Narvalex

3

只是爲了在第5點我已經告訴Facebook並使用ES最終一致性,這就是爲什麼你有時可以看到一個貼子消失,你已經張貼後再次出現意見。

通常,您的瀏覽器正在訪問的讀取模型與您位於「接近」位置,但在發佈後,SPA會切換到與您的寫入模型接近的讀取模型。寫模型(事件)和閱讀模型之間的距離很近,這意味着您可以看到自己的帖子。

但是,15分鐘後,您的SPA切換回第一個更接近的閱讀模型。如果包含帖子的事件尚未傳播到該讀取模型,您將看到自己的帖子消失,僅在稍後重新出現。

相關問題