CQRS 是一種 微服務(wù) 架構(gòu)模式 ,它代表命令和查詢責(zé)任分離。
這種模式背后的基本思想是將寫操作與讀操作分開。不是使用一個(gè)數(shù)據(jù)存儲(chǔ)來執(zhí)行 CRUD 操作,而是在一個(gè)數(shù)據(jù)存儲(chǔ)上執(zhí)行讀取操作,并在不同的數(shù)據(jù)存儲(chǔ)上執(zhí)行創(chuàng)建/更新。
CQRS 承諾對(duì)大規(guī)模應(yīng)用程序的穩(wěn)定性和可 擴(kuò)展性 以及顯著的性能改進(jìn)。
CQRS 模式由 Bertrand Meyer 設(shè)計(jì),作為開發(fā) Eiffel 編程語言的一部分。Greg Young 創(chuàng)造了“CQRS”一詞。
CQRS 在哪里使用?
CQRS 通常在準(zhǔn)備就緒的大規(guī)模分布式應(yīng)用程序中是首選。也就是說,如果應(yīng)用程序中的讀取次數(shù)遠(yuǎn)遠(yuǎn)超過寫入操作的次數(shù)。
此模式的另一個(gè)合適用例是讀取操作繁重且數(shù)據(jù)存儲(chǔ)副本可以放置在應(yīng)用程序接收高流量的地理位置附近,從而提高數(shù)據(jù)庫讀取操作的性能。
CQRS 是如何實(shí)現(xiàn)的?
到目前為止,我們知道要實(shí)現(xiàn) CQRS ,我們將使用兩個(gè)數(shù)據(jù)存儲(chǔ)庫。
通常,寫入操作首選關(guān)系數(shù)據(jù)庫,其中可以應(yīng)用所有數(shù)據(jù)約束,并使用NoSQL 數(shù)據(jù)庫支持讀取操作。這意味著,兩種不同的數(shù)據(jù)模型用于寫入和讀取操作。
自然,人們會(huì)想到的問題是這兩個(gè)存儲(chǔ)庫中的數(shù)據(jù)如何同步?
這就是事件驅(qū)動(dòng) 架構(gòu) 出現(xiàn)的地方。
考慮一個(gè)用戶調(diào)用POST API的場(chǎng)景,執(zhí)行一些驗(yàn)證,然后將數(shù)據(jù)及其約束更新到我們的關(guān)系數(shù)據(jù)庫中。
將數(shù)據(jù)插入數(shù)據(jù)庫后,將調(diào)用觸發(fā)器,該觸發(fā)器將更新所有事件處理程序(事件驅(qū)動(dòng)架構(gòu))以更新讀取的數(shù)據(jù)庫。
當(dāng)另一個(gè)用戶調(diào)用 GET API 時(shí),應(yīng)用程序?qū)腘oSQL 數(shù)據(jù)庫中檢索相關(guān)數(shù)據(jù)并將其發(fā)送回用戶。用于實(shí)現(xiàn) CQRS 的最流行的基于 JAVA 的框架是 Axon。
Axon 使用命令和處理程序來調(diào)用和處理相應(yīng)的事件。 你可以在Github 上找到完整的代碼。
使用 CQRS 有什么好處?
使用 CQRS 的主要好處包括:
靈活的擴(kuò)展——讀寫數(shù)據(jù)存儲(chǔ)可以根據(jù)需求獨(dú)立擴(kuò)展。 簡(jiǎn)單查詢——由于讀取和寫入的數(shù)據(jù)模型是分開的,讀取數(shù)據(jù)模型可以設(shè)計(jì)成避免復(fù)雜查詢的方式。 提高性能——通過優(yōu)化讀取操作并將數(shù)據(jù)存儲(chǔ)副本放置在不同的地理位置,讀取繁重的操作可以顯著提高性能。使用 CQRS 的缺點(diǎn)是什么?
復(fù)雜性——事件驅(qū)動(dòng)的系統(tǒng)構(gòu)建和維護(hù)起來很復(fù)雜。盡管有像 Axon 這樣的框架可以處理數(shù)據(jù)庫寫入、發(fā)布事件和通知各種處理程序,但也有讀寫模型不同步的情況。 一致性——CQRS 和事件驅(qū)動(dòng)架構(gòu)旨在確保數(shù)據(jù)在所有涉及的系統(tǒng)中保持一致,但在消息失敗的情況下,讀取數(shù)據(jù)庫將不同步。結(jié)論
在讀取次數(shù)遠(yuǎn)大于寫入次數(shù)的情況下,CQRS 是一種需要考慮的模式。特別是在讀取操作要高度優(yōu)化并且不需要執(zhí)行任何業(yè)務(wù)邏輯或驗(yàn)證的情況下。讀取操作就像獲取數(shù)據(jù)、加載 DTO 并將其傳遞給客戶端一樣簡(jiǎn)單。
實(shí)現(xiàn)這樣一個(gè)系統(tǒng)的最大挑戰(zhàn)是確保避免數(shù)據(jù)重復(fù),讀取數(shù)據(jù)庫永遠(yuǎn)不會(huì)過時(shí),并且寫入數(shù)據(jù)庫的所有條目最終也會(huì)在讀取數(shù)據(jù)庫中一致地更新。
盡管從概念上講,這聽起來很簡(jiǎn)單,但 CQRS 并不那么容易實(shí)現(xiàn)和調(diào)試。