如何設(shè)計(jì)事件流,第 4 部分
在之前部分中,我們從宏觀角度考慮了我們的數(shù)據(jù),并區(qū)分了內(nèi)部數(shù)據(jù)和外部數(shù)據(jù)。我們還討論了模式和數(shù)據(jù)契約,以及它們?nèi)绾翁峁╇S著時(shí)間的推移協(xié)商、更改和發(fā)展我們的流的方法。最后,我們介紹了事實(shí)(狀態(tài))和增量事件類型。事實(shí)事件最適合通信狀態(tài)和解耦系統(tǒng),而 Delta 事件往往更多地用于內(nèi)部數(shù)據(jù),例如在事件溯源和其他緊密耦合的用例中。
規(guī)范化表創(chuàng)建規(guī)范化流
規(guī)范化的表導(dǎo)致規(guī)范化的事件流。連接器(例如,CDC)將數(shù)據(jù)直接從數(shù)據(jù)庫(kù)拉入事件流的鏡像集。這并不理想,因?yàn)樗趦?nèi)部數(shù)據(jù)庫(kù)表和外部事件流之間創(chuàng)建了強(qiáng)耦合。
考慮一個(gè)簡(jiǎn)單的電子商務(wù)項(xiàng)目及其關(guān)聯(lián)的品牌和稅收狀態(tài)表。
品牌和稅收狀態(tài)表通過(guò)外鍵關(guān)系與項(xiàng)目表相關(guān)。雖然我們只在表中顯示一項(xiàng),但您可能會(huì)有數(shù)千(或數(shù)百萬(wàn))項(xiàng),具體取決于您銷售的產(chǎn)品。
通常為每個(gè)表設(shè)置一個(gè)連接器,從表中提取數(shù)據(jù),將其組合成事件,并將每個(gè)表寫(xiě)入專用的事件流。
公開(kāi)數(shù)據(jù)庫(kù)中的基礎(chǔ)表會(huì)導(dǎo)致每個(gè)表產(chǎn)生相應(yīng)的事件流。雖然這種方式很容易上手,但它會(huì)導(dǎo)致多個(gè)問(wèn)題,這些問(wèn)題可以概括為耦合 問(wèn)題或成本 問(wèn)題。讓我們逐一看看。
問(wèn)題:消費(fèi)者對(duì)內(nèi)部模型的耦合
按原樣公開(kāi)源Item表會(huì)迫使消費(fèi)者直接耦合它。源系統(tǒng)數(shù)據(jù)模型的更改將影響下游消費(fèi)者。
假設(shè)我們重構(gòu)Item表以將P ricing提取到它自己的表中。
重構(gòu)源表會(huì)導(dǎo)致項(xiàng)目流的數(shù)據(jù)契約損壞。不再向消費(fèi)者提供他們最初期望的相同商品數(shù)據(jù)。我們還必須創(chuàng)建一個(gè)新的連接器 - 一個(gè)新的P米流 - 最后,重構(gòu)我們的消費(fèi)者邏輯 以使其再次運(yùn)行。重命名列、更改默認(rèn)值和更改列類型是內(nèi)部數(shù)據(jù)模型上的緊密耦合引入的其他形式的破壞性更改。
問(wèn)題:流式連接(通常)昂貴
關(guān)系數(shù)據(jù)庫(kù)是專門(mén)為快速、廉價(jià)地解決連接問(wèn)題而構(gòu)建的。不幸的是,流連接不是這樣的。
考慮兩個(gè)需要訪問(wèn)Item、其Tax及其Brand信息的服務(wù)。如果數(shù)據(jù)已寫(xiě)入其相應(yīng)的流,則每個(gè)使用者(下圖中的右側(cè))將必須計(jì)算相同的連接來(lái)對(duì)Item、B rand和T ax進(jìn)行非規(guī)范化。
此策略可能會(huì)產(chǎn)生高昂的成本,無(wú)論是編寫(xiě)應(yīng)用程序的開(kāi)發(fā)時(shí)間還是計(jì)算連接的服務(wù)器成本。大規(guī)模解決流連接可能會(huì)導(dǎo)致大量數(shù)據(jù)洗牌,從而產(chǎn)生處理能力、網(wǎng)絡(luò)和存儲(chǔ)成本。此外,并非所有流處理框架都支持連接,尤其是外鍵連接。在那些這樣做的語(yǔ)言中,例如 Flink、Spark、KSQL 或 Kafka Streams(例如),您會(huì)發(fā)現(xiàn)自己僅限于編程語(yǔ)言的子集(Java、Scala、Python)。
解決方案:提供非規(guī)范化數(shù)據(jù)是最好的
原則上,應(yīng)使事件流易于消費(fèi)者使用。在使用抽象層將數(shù)據(jù)提供給消費(fèi)者之前對(duì)其進(jìn)行非規(guī)范化,并創(chuàng)建顯式的外部模型數(shù)據(jù)契約 (外部數(shù)據(jù))以供消費(fèi)者耦合。
對(duì)內(nèi)部模型的更改在源系統(tǒng)中保持隔離。消費(fèi)者獲得一個(gè)定義明確的數(shù)據(jù)契約來(lái)進(jìn)行耦合。只要源系統(tǒng)為消費(fèi)者維護(hù)數(shù)據(jù)契約,對(duì)源模型所做的更改就可以不受阻礙地進(jìn)行。
但是我們?cè)谀睦锓且?guī)范化呢?兩種選擇:
· 通過(guò)專門(mén)構(gòu)建的連接器服務(wù)在源系統(tǒng)外部進(jìn)行重建。
· 在使用事務(wù)發(fā)件箱模式在源系統(tǒng)中創(chuàng)建事件期間。