架構(gòu)設(shè)計(jì)系列文章,請(qǐng)參見(jiàn)連接剩檀。
介紹
命令查詢(xún)責(zé)任分離源于Bertrand Mayer設(shè)計(jì)的命令查詢(xún)分離(CQS)原理。CQS聲明一個(gè)類(lèi)只能有兩種方法:改變狀態(tài)并返回void的方法和返回狀態(tài)但不改變它的方法坏逢。后來(lái)經(jīng)過(guò)Greg Young的發(fā)展與推廣最終形成了現(xiàn)在的CQRS。
講解
命令查詢(xún)的責(zé)任分離(Command Query Responsibility Segregation痒谴,簡(jiǎn)稱(chēng)CQRS)模式包含著兩部分:能夠使改變模型的狀態(tài)的命令和模型狀態(tài)的查詢(xún)。CQRS是DDD應(yīng)用領(lǐng)域的一個(gè)模式铡羡,主要解決DDD在數(shù)據(jù)庫(kù)報(bào)表輸出上處理方式积蔚。
在DDD架構(gòu)中,通常會(huì)將查詢(xún)和命令操作分開(kāi)蓖墅,具體落地時(shí)库倘,是否將查詢(xún)和命令分開(kāi)成為兩個(gè)項(xiàng)目可以視情況而定,大多數(shù)情況下放在一個(gè)項(xiàng)目可以提高業(yè)務(wù)內(nèi)聚性论矾。也可以在邏輯層面上劃分為兩個(gè)不同的操作模型(Command和Query)但是在物理層面上還是使用同一個(gè)數(shù)據(jù)庫(kù)進(jìn)行。
對(duì)于CQRS來(lái)說(shuō)最主要的是改變狀態(tài)和獲取狀態(tài)的兩類(lèi)操作杆勇,只要將這兩類(lèi)動(dòng)作分離的都可以稱(chēng)作是CQRS贪壳。這樣拆離之后對(duì)于查詢(xún)DTO和命令DTO就也可以分離出來(lái)。大多數(shù)時(shí)候蚜退,改變狀態(tài)所需的數(shù)據(jù)在形式或數(shù)量上都不同于用戶(hù)需要查詢(xún)所需的數(shù)據(jù)闰靴。使用相同的模型來(lái)一起處理查詢(xún)和命令會(huì)會(huì)導(dǎo)致模型膨脹,只依靠一種類(lèi)型來(lái)操作所需的所有東西钻注,模型復(fù)雜性也會(huì)增加蚂且,聚合大小通常會(huì)更大。
模式描述
對(duì)于命令查詢(xún)職責(zé)分離模式可以有兩種變種模式:CQRS幅恋,CQRS/ES杏死。CQRS是對(duì)命令和查詢(xún)使用不同的服務(wù)器。而CQRS/ES是使用溯源事件的方式將用戶(hù)命令發(fā)送到讀數(shù)據(jù)庫(kù)中捆交。Event Sourcing是由Martin Fowler提出淑翼,是將業(yè)務(wù)領(lǐng)域精髓(尤其是最復(fù)雜的)與技術(shù)平臺(tái)的復(fù)雜性實(shí)現(xiàn)脫鉤的天作之合。為什么要用Event Sourcing?或 Domain Events – 救世主
在這兩種模式的選擇中也分為有兩個(gè)陣營(yíng):一個(gè)說(shuō)你應(yīng)該總是使用CQRS / ES品追,另一個(gè)說(shuō)你應(yīng)該只使用你的解決方案的一部分玄括,并且只有當(dāng)你需要具有高性能/可用性/可擴(kuò)展性系統(tǒng)的高度并發(fā)系統(tǒng)時(shí)。您應(yīng)該始終根據(jù)您的要求評(píng)估您的選擇肉瓦。
CQRS使我們能夠使用不同的模型來(lái)改變狀態(tài)和不同的模型來(lái)支持查詢(xún)遭京。通常寫(xiě)操作的頻率低于讀操作。 具有單獨(dú)的模型和分離的數(shù)據(jù)庫(kù)引擎允許我們獨(dú)立地?cái)U(kuò)展查詢(xún)端并更好地處理并發(fā)訪(fǎng)問(wèn)泞莉,因?yàn)樽x取端不再堵塞寫(xiě)入或命令端(在相反的情況下)哪雕。
對(duì)于讀寫(xiě)數(shù)據(jù)庫(kù)數(shù)據(jù)結(jié)構(gòu)不一致或純粹不一致的數(shù)據(jù)庫(kù)的情況下,可以通過(guò)Event Sourcing的方式進(jìn)行支撐戒财。并且Event Sourcing的方式還可以進(jìn)行消息記錄热监。
特點(diǎn)
-
開(kāi)發(fā)
過(guò)程管理(康威定律)
CQRS/ES增加了平臺(tái)的復(fù)雜度。需要在實(shí)施過(guò)程中以過(guò)程的方法解決復(fù)雜度增加造成的問(wèn)題饮寞。可測(cè)試性
CQRS/ES的測(cè)試點(diǎn)較多孝扛。并且因?yàn)閺?fù)雜的增加可能會(huì)造成測(cè)試過(guò)程中問(wèn)題反復(fù)列吼。可擴(kuò)展性
CQRS/ES最主要的目標(biāo)就是為了高性能/可用性/可擴(kuò)展性系統(tǒng)而設(shè)計(jì)的。所以對(duì)于可擴(kuò)展性的支持較好苦始。
-
運(yùn)維
可伸縮
CQRS/ES最主要的目標(biāo)就是為了高性能/可用性/可擴(kuò)展性系統(tǒng)而設(shè)計(jì)的寞钥。所以對(duì)于可伸縮性的支持較好。部署難易
CQRS/ES系統(tǒng)中涉及到多服務(wù)部署的問(wèn)題陌选,需要在上線(xiàn)時(shí)進(jìn)行配置理郑。維護(hù)難易
穩(wěn)定性尚可,但是可跟蹤性比較弱咨油。所以維護(hù)難度比較高您炉。
-
性能
CQRS/ES最主要的目標(biāo)就是為了高性能/可用性/可擴(kuò)展性系統(tǒng)而設(shè)計(jì)的。所以對(duì)于性能的支持較好役电。
總結(jié):
在互聯(lián)網(wǎng)高并發(fā)的情況下經(jīng)常使用CQRS架構(gòu)作為整體架構(gòu)赚爵,然后再在CQRS內(nèi)部使用其他的架構(gòu)模式配合形成一套完整的架構(gòu)。幫我們解決了很多關(guān)于性能法瑟、穩(wěn)定性冀膝、數(shù)據(jù)拆分的問(wèn)題。對(duì)于CQRS的特點(diǎn)可以總結(jié)為將用戶(hù)操作與頁(yè)面展示分離霎挟,可以使用靜態(tài)化窝剖、緩存的方式解決讀速度的問(wèn)題。所以在CQRS中并沒(méi)有限制在系統(tǒng)中使用同構(gòu)數(shù)據(jù)庫(kù)/數(shù)據(jù)源作為數(shù)據(jù)存儲(chǔ)與查詢(xún)做管理酥夭。在結(jié)合Event Sourcing的方式進(jìn)行數(shù)據(jù)的更新操作赐纱。可以滿(mǎn)足系統(tǒng)大量查詢(xún)的情況采郎。
參考
CQRS
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式千所、原理與實(shí)踐
CQRS架構(gòu)
解決CQRS中的復(fù)雜問(wèn)題
最全面的CQRS和事件溯源介紹 - Software House ASC