如何設(shè)計事件流,第 3 部分
Delta Events 支持事件溯源
但是三角洲事件呢?
他們的主要用例之一是事件溯源。要組合當(dāng)前狀態(tài),您可以將每個更改記錄為其自己的事件,然后使用特定的狀態(tài)組合邏輯按順序應(yīng)用這些事件。這是一種事件驅(qū)動模式,用于構(gòu)建內(nèi)部有數(shù)據(jù)的系統(tǒng),因為事件和狀態(tài)組合邏輯之間存在緊密耦合的關(guān)系。
事件溯源:從一系列增量構(gòu)建狀態(tài)
每當(dāng)數(shù)據(jù)字段更新時都會觸發(fā)事實事件,而每當(dāng)滿足特定業(yè)務(wù)邏輯條件時就會觸發(fā)增量事件。例如,item_added_to_cart只要將商品添加到購物車,就會觸發(fā)該事件。
一個購物車事實事件與兩個與購物車相關(guān)的增量事件
Delta 適合捕捉變更背后的意圖。它們通常用于向消費(fèi)者傳遞通知(例如,食物已準(zhǔn)備好取貨、收到電子郵件/文本/消息),這可以提供有用的信號解決方案。
但增量很容易被濫用。一方面,客戶傾向于要求細(xì)粒度的定制活動來滿足下游消費(fèi)者的需求。例如,“當(dāng)購物車中添加了 15 件商品時通知我”,或者“當(dāng)客戶在過去 90 天內(nèi)在鞋子上花費(fèi)了 1000 美元時通知我”。雖然這些通知對于消費(fèi)者的業(yè)務(wù)部門可能至關(guān)重要,但它們將確定條件的責(zé)任交給了數(shù)據(jù)生產(chǎn)者——將責(zé)任轉(zhuǎn)移到上游,并模糊了哪個系統(tǒng)負(fù)責(zé)哪個計算。
Delta 不適合在外部重建狀態(tài)
相反,將特定于消費(fèi)者的業(yè)務(wù)邏輯放在下游、關(guān)心檢測這些條件并根據(jù)這些條件采取行動的服務(wù)內(nèi)部。然后,依靠狀態(tài)事件來確定這些情況何時發(fā)生。
復(fù)合事件
第三種類型的事件是復(fù)合事件:它是事實和增量的組合。
從事實事件開始,您可以添加有關(guān)創(chuàng)建該事件的原因的信息。在下面的示例中,我們將“item_added_to_cart”事件創(chuàng)建的原因包括在內(nèi)(盡管您也可以根據(jù)自己的狀態(tài)自行推斷)。
帶有“原因”字段的購物車事實,表明其創(chuàng)建原因
同樣,您可以選擇將其包含在“before/after”事件中,如下所示:
具有之前/之后字段的復(fù)合購物車事件
“reason”請注意,向事件添加 a可能會引入與源系統(tǒng)的強(qiáng)耦合。您可能已經(jīng)注意到:“嘿 Adam,這不就是事實中嵌入的三角洲的名稱嗎?”你是對的。正是如此。
需要明確的是,我不提倡使用復(fù)合事件,因為它們在上游系統(tǒng)的原因填充邏輯上引入了緊密耦合。原因中可能包含很多語義,消費(fèi)者可能很難理解它們——特別是當(dāng)添加新語義或刪除舊語義時。
這只是構(gòu)建復(fù)合事件的一種方法。您可能還想知道,“但是 Adam,包含某種狀態(tài)的 delta 事件怎么樣?”。雖然從理論上講,您可以通過這種方式構(gòu)建復(fù)合事件,但現(xiàn)實情況是,大多數(shù)增量事件都非常精簡,根本不包含任何狀態(tài) - 僅包含轉(zhuǎn)換信息。部分原因在于慣例(喜歡使用增量的開發(fā)人員通常會盡量減少通過線路發(fā)送的所有數(shù)據(jù)),部分原因在于邊界。我們已經(jīng)了解了為什么強(qiáng)制消費(fèi)者根據(jù)增量計算狀態(tài)是有問題的。
現(xiàn)實情況是,復(fù)合事件在野外相對較少。我將它們包含在這篇博文中,因為您可能會在自己現(xiàn)有的系統(tǒng)中遇到它們。我從未發(fā)現(xiàn)我需要在實踐中創(chuàng)建復(fù)合事件,而是偏向于外部數(shù)據(jù)的狀態(tài)事件,為內(nèi)部用例的數(shù)據(jù)留下增量(以及上面提到的原因字段)。
讓我們從復(fù)合事件開始,回到觀察狀態(tài)。如果您想要傳達(dá)大量狀態(tài),但它不適合事件,您該怎么辦?為此,您需要使用索賠支票。
索賠檢查模式
聲明檢查是您在事件中嵌入 URI 的位置,以便消費(fèi)者可以在需要時訪問它以獲取更多信息。包含additional_state field一個 URI,您可以在其中獲取附加信息,例如文件存儲、數(shù)據(jù)庫或 REST 接口。
使用聲明檢查模式的附加狀態(tài)
聲明檢查使您可以輕松地將狀態(tài)存儲卸載到另一個事件,同時包含大多數(shù)事件使用者需要的公共信息。它可以減少通過網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量和成本。當(dāng)數(shù)據(jù)非常大時,尤其是在不常用的情況下(例如,電子商務(wù)項目的完整純文本評論集),聲明檢查模式可能很有用。
但是,請記住,實現(xiàn)此模式有幾個主要考慮因素,包括:
· 訪問控制:確保只有適當(dāng)?shù)氖褂谜卟拍茏x取附加狀態(tài)
· 存儲:確保additional_state僅在刪除或壓縮事件時刪除數(shù)據(jù)
· 模式:URI 中的數(shù)據(jù)additional_state將有自己的模式和格式。您需要確保消費(fèi)者可以輕松閱讀它,并且不會發(fā)生任何計劃外的重大更改。協(xié)調(diào)事件版本和additional_state版本演變也可能具有挑戰(zhàn)性。
· 可重玩性:不變性是可重玩性的一個關(guān)鍵概念。如果您選擇實施聲明檢查,則需要確保您的 URI 指向該時間點的數(shù)據(jù)快照。一個常見的反模式是指向數(shù)據(jù)庫表中的當(dāng)前狀態(tài),這不提供可重播性,因為additional_state每次更改都會被覆蓋。
請謹(jǐn)慎行事,因為您可能會發(fā)現(xiàn)上述復(fù)雜性超過了好處。
我什么時候應(yīng)該使用事實與增量?
下表很好地總結(jié)了這一點。
事件流構(gòu)成了任何事件驅(qū)動架構(gòu)的基石,正確的設(shè)計是一個重要的起點。精心設(shè)計的流可以輕松傳達(dá)重要的業(yè)務(wù)事件,以便感興趣的消費(fèi)者可以按照自己的節(jié)奏閱讀、攝取、存儲和響應(yīng)這些事件。
您必須考慮流的角色 - 它會提供內(nèi)部數(shù)據(jù)還是外部數(shù)據(jù)?事實是一種靈活且有彈性的模型,可用于構(gòu)建您的事件,但它們往往更大并且需要使用更多的在線數(shù)據(jù)。然而,與 delta 相比,它們完全隔離了上游系統(tǒng)的內(nèi)部邏輯,可以輕松構(gòu)建彈性解耦的消費(fèi)者來服務(wù)于特定的業(yè)務(wù)目的。