
本文是讀完Martin Kleppmann的《Making sense of stream processing》的一些理解和感悟。
Event Sourcing (事件溯源)、Stream processing(流處理)、Complex Event Processing(復(fù)雜事件處理)、CQRS(Command Query Responsibility Segregation,命令查詢(xún)職責(zé)分離)、Event-driven architecture(事件驅(qū)動(dòng)架構(gòu))等令人眼花繚亂的技術(shù)術(shù)語(yǔ)的本質(zhì)是事件和事件流,這些技術(shù)的區(qū)別在于對(duì)事件的粒度的劃分和對(duì)事件處理過(guò)程的側(cè)重點(diǎn)。
1. Event Sourcing (事件溯源)
Event Sourcing側(cè)重于事件的持久化,這里的事件的粒度可以細(xì)到對(duì)業(yè)務(wù)數(shù)據(jù)的增刪改查,如果和傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)做對(duì)比,傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)記錄的數(shù)據(jù)是一種最終狀態(tài),這個(gè)狀態(tài)可以被隨時(shí)增刪改查,而Event Sourcing記錄的數(shù)據(jù)則是對(duì)狀態(tài)進(jìn)行增刪改的有序命令流,每條數(shù)據(jù)本省不可被更改,但依據(jù)這些命令流可以構(gòu)造出最終的狀態(tài):

正如Martin所舉的電商購(gòu)物車(chē)的例子,傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)表中記錄的是用戶、商品和數(shù)量的信息,是最終結(jié)果:

而事件溯源則記錄用戶的每一次添加商品、更新數(shù)量、提交訂單操作,是有序的命令流:

實(shí)現(xiàn)Event Sourcing并不難,Event Store這款開(kāi)源數(shù)據(jù)庫(kù)就可以幫助我們存儲(chǔ)事件以及進(jìn)行復(fù)雜查詢(xún),還有很多新玩法等著我們?nèi)?shí)踐。
2. Stream processing(流處理)
Stream processing側(cè)重于事件處理的過(guò)程,這里的事件的粒度偏向于實(shí)時(shí)的業(yè)務(wù)數(shù)據(jù),Martin稱(chēng)之為Raw Event,如每秒的室內(nèi)溫度數(shù)據(jù)、用戶當(dāng)前發(fā)布的微博等,由于數(shù)據(jù)量大且實(shí)時(shí)要求高,流處理一般采用分布式架構(gòu)?;谶@些原始事件,可以構(gòu)建上層的實(shí)時(shí)統(tǒng)計(jì)、聚合的邏輯,從而生成Aggregated Data,當(dāng)然也可以構(gòu)建離線分析的邏輯,所以原始事件是實(shí)現(xiàn)流處理的基礎(chǔ),聚合數(shù)據(jù)只是最終呈現(xiàn)的結(jié)果。
近年來(lái)隨著Twitter、Facebook等互聯(lián)網(wǎng)公司的發(fā)展,分布式流式計(jì)算逐漸成熟。這些互聯(lián)網(wǎng)公司的業(yè)務(wù)數(shù)據(jù)有一個(gè)共同點(diǎn),即有大量的并發(fā)的讀寫(xiě)操作,在這種業(yè)務(wù)場(chǎng)景下傳統(tǒng)的以關(guān)系型數(shù)據(jù)庫(kù)為核心的系統(tǒng)架構(gòu)已經(jīng)不能勝任,只能將數(shù)據(jù)讀寫(xiě)操作分離,構(gòu)建新的解決方案,保證高可用性和高一致性。分布式流式計(jì)算是可以實(shí)現(xiàn)讀寫(xiě)分離的一種架構(gòu),也正是讀寫(xiě)分離讓流處理和事件溯源的產(chǎn)生了邏輯上的內(nèi)在一致性:在兩種技術(shù)中事件在本質(zhì)上講都是數(shù)據(jù)的寫(xiě)操作,或者說(shuō)是更新操作,流處理中的聚合數(shù)據(jù)和事件溯源里的狀態(tài)及查詢(xún)是數(shù)據(jù)讀操作的結(jié)果:

典型的分布式流式計(jì)算的架構(gòu)是這樣的:

關(guān)于讀寫(xiě)分離,Martin在文中還進(jìn)行了一種有意思的抽象:應(yīng)用程序里面產(chǎn)生后臺(tái)交互的Button對(duì)應(yīng)寫(xiě)操作,而Screen頁(yè)面上展示的的結(jié)果對(duì)應(yīng)讀操作,雖然不夠嚴(yán)謹(jǐn)?shù)阋阅軌蛘f(shuō)明,事件的范疇在當(dāng)前的Web端和Mobile端應(yīng)用程序中已經(jīng)不僅僅是傳統(tǒng)的交易數(shù)據(jù),用戶的每一次點(diǎn)擊動(dòng)作和瀏覽記錄都是能產(chǎn)生寫(xiě)操作事件,你打開(kāi)淘寶的一瞬間,事件就會(huì)源源不斷地產(chǎn)生,可謂“買(mǎi)賣(mài)未動(dòng),數(shù)據(jù)先行”。
3. Complex Event Processing(復(fù)雜事件處理)
CEP同樣側(cè)重于事件處理的過(guò)程,但是更強(qiáng)調(diào)事件之間存在復(fù)雜的關(guān)系,如時(shí)間順序關(guān)系/聚合關(guān)系/層次關(guān)系/依賴(lài)關(guān)系。CEP需要構(gòu)建規(guī)則引擎,對(duì)符合一定Pattern的事件進(jìn)行查詢(xún)和處理。這其中比較優(yōu)秀的工具有Esper和Flink CEP。

Flink官網(wǎng)的一個(gè)簡(jiǎn)單案例足以說(shuō)明復(fù)雜事件處理和流處理結(jié)合后的威力:數(shù)據(jù)中心機(jī)架的溫度被實(shí)時(shí)監(jiān)控,溫度超過(guò)閾值時(shí)會(huì)產(chǎn)生Warning事件,連續(xù)兩個(gè)Warning事件會(huì)產(chǎn)生Alert事件,Alert事件則會(huì)觸發(fā)降溫的動(dòng)作,在樣的業(yè)務(wù)邏輯在Flink平臺(tái)上用短短幾行代碼就可以實(shí)現(xiàn),而用普通手段則要復(fù)雜得多。CEP可以提高系統(tǒng)的監(jiān)控和分析能力。
4. CQRS (Command Query Responsibility Segregation,命令查詢(xún)職責(zé)分離)
CQRS上升到了系統(tǒng)架構(gòu)這個(gè)層次,事件的粒度是系統(tǒng)中的業(yè)務(wù)數(shù)據(jù)。在架構(gòu)層面,將一個(gè)系統(tǒng)分為寫(xiě)入(命令)和查詢(xún)兩部分。一個(gè)命令表示一種意圖,表示命令系統(tǒng)做什么修改,命令的執(zhí)行結(jié)果通常不需要返回;一個(gè)查詢(xún)表示向系統(tǒng)查詢(xún)數(shù)據(jù)并返回。同樣是讀寫(xiě)分離,互聯(lián)網(wǎng)場(chǎng)景下的流式計(jì)算中的讀寫(xiě)分離是為了解決高并發(fā)讀寫(xiě)操作,而CQRS中的讀寫(xiě)分離則是為了解決復(fù)雜的數(shù)據(jù)模型,是Domain Driven Design(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))的實(shí)踐。

5. Event-driven architecture(事件驅(qū)動(dòng)架構(gòu))
在事件驅(qū)動(dòng)架構(gòu)中,事件的粒度為多進(jìn)程、多服務(wù)、多系統(tǒng)之間的通信消息。不同于SOA架構(gòu),EDA架構(gòu)是pub-sub模式:Process1處理完邏輯后產(chǎn)生消息,Process2訂閱消息并進(jìn)行處理, Process1不知道Process2的存在,Process間通過(guò)MQ最終數(shù)據(jù)的最終一致性。
