事件溯源很難 - Blogomatano
我將直接告訴你:事件溯源Event Sourcing實際上有缺點的,如果您在網際網路上閱讀了有關該主題的任何內容,這句話肯定會讓您感到震驚。畢竟,它通常是給人一種陽光和彩虹的美好感覺,當你遇到了什麼問題時,都可以通過事件溯源來解決的。你生活中的大部分煩惱可能都是由於 缺乏 事件溯源造成的。
您已被網際網路誘惑,也許意味只要開始事件溯源之旅就能過上美好的生活。好吧,在你這樣做之前,我揭露真相,告訴你走上這個旅程實際上並不充滿純粹喜悅的,而是一個裝滿地雷的袋子,炸傷你的腿然後把你丟在充滿痛苦的殘缺的生活中。
我為什麼要這樣說呢?因為以前我是一個有能力進行設計,讓團隊走上了從頭開始構建事件源系統的道路。在經歷了複雜的應用程式部署之後,我獲得了大量的傷疤、瘀傷和經驗教訓,以下是我伴隨著事件溯源發展過程的意見,意外障礙,錯誤假設,不良理解。
前言
要明確的是,這不是說“你永遠不應該是事件源”,或者“事件溯源是有史以來最糟糕的事情”,這只是在將事件溯源動力系統引入時出現的意外成本和生產中出現問題的集合。其中大部分可能屬於“他顯然不理解X”,或“你 永遠 不應該做Y!” 在這種情況下,你是絕對正確的。重點是,在我走過“玩具”階段之前,我不明白其中缺點或痛點。
Event Sourcing的核心賣點主要是反模式
大型事件溯源是指任何感興趣的子系統都可以訂閱事件流並愉快地偵聽事件然後完成其工作。這張圖片幾乎可以在任何事件溯源介紹中找到:
在實踐中,這可以在某種程度上同時兼具極端耦合但極其不透明。保持多個服務可以訂閱和釋出的中央日誌的想法是瘋狂的。在 不進行 事件處理時,您不會讓兩個單獨的服務直接進入彼此的資料儲存- 您需要通過一個抽象層來抽取它們,以避免在需要更改其資料時破壞您服務的每個消費者 - 但是,事件日誌的情況並非如此:它是“直接到達並抓住那些原始資料事件”,它們是不可改變的“事實”,不變的東西不會改變,對吧?
實際上,原始事件流的訂閱會破壞本地邏輯推理服務邊界的能力。在“正常”開發流程下,您可以在安全,舒適的小邊界內操作,構成您的服務。您可以自由選擇實施和儲存,然後,當您準備好時,需要處理這些事情如何暴露給外部世界,這是“服務”的核心優勢之一。但是,當人們進入您的資料儲存並直接閱讀您的事件時,該“黑匣子”屬性就會消失。協調不能在之後進行,您必須與將要使用您生成的事件的消費者進行互動,以確保事件包含足夠的資料供消費者做出決策。
如果您通過上述障礙進行戰鬥並通過事件流成功連線一組服務,您將獲得一個新問題:不透明度。多個系統讀取事件流導致了一個協調層,處理 怎麼把 這些系統連線到一起,最終將完全莫名其妙。你基本上得到 了Observer重量程式碼所帶來的所有問題 ,而且是在系統級別上。控制變得顛倒,導致很難推斷資料如何實際流過系統,或者哪些系統消耗/產生事件,或者關心它們是否被新增/刪除/修改等等。
現在,公平地說,Greg Young 有一個講話 ,他提到了這些問題並提倡通過流程管理器或簡單的基於Actor的設計來解決它們,即引入可以作為可以路由事件的中心協調點的東西。但是,直到很久以後我才看到這種說法。我在想,分類帳會統治世界的,只好慢慢地發現通過痛苦地失敗才發現這點。
新貴成本很高
當你是一個綠色的現場應用程式時,事件溯源不是一種“ 快速移動和容易破碎 ”的系統。這更像是一個“ 讓我們慢慢移動,儘量不死 ”的系統。首先,您 可能 會從頭開始構建核心元件,該領域的框架往往是重量級,過於規範,並且在技術堆疊方面缺乏靈活性,如果你想在公司環境中使用 今天 可用的技術並在執行中獲得一些東西,那麼不斷髮展你自己的方法就是可行的方法( 以及建議的方法! )。
雖然這條道路充滿樂趣,這也是超級耗時的,在計劃如何在可用的基礎架構上部署內容,如何確保流的行為,訊息處理,如何重試失敗, 然後 你必須實際地執行它,然後進行衝刺時又會放棄你的選擇,用你新獲得的知識再次實現它,直到你最終有一個足夠堅實的基礎,你可以真正開始構建有問題的應用程式了。
一旦你進入實施階段,你就會意識到其他的事情:所涉及的管道程式碼的剪下量是驚人的。你現在已經得到了命令,命令處理程式,命令驗證,事件,聚集類, 並且那麼 你的預測,這些模型類,它們的訪問類,自定義物化程式碼,等等。從零到工作基線需要大量的腳手架。現在,不可否認,這種傷害有多依賴於語言,但如果你是在使用一種像Java這樣冗長的語言(就像我一樣),你的手指會在每天結束時都會感到疲憊。
作為“入門”方面的最後一點,涉及一定的人力/政治成本。在哲學上獲得整個開發團隊支援是非常重要的,然而,分歧仍然會增加的。這些團隊問題可能會在您的直接開發組之外蔓延。讓涉及使用者體驗的第三方成員面臨挑戰。這導致意想不到的......
事件溯源需要UI方面發揮作用
這一點,雖然回想起來很明顯,讓我感到意外。如果你有一個UI,它通常需要與後端的事件驅動方面一起玩。意思是,它應該是 基於任務的 。但是,大多數常見的UI迭代 都不是這樣 設計的。它們是靜態的,基於表單的。這意味著你最終會在需要小型語義事件的後端和前端之間出現大規模的阻抗不匹配,前端會給你豐富的表單資料。
一個常見的反應可能是應用程式的那些重型表單部分可能根本不應該寫入分類帳 :CRUD就是CRUD(banq注:橋歸橋 路歸路,表單資料不應進入事件源系統)。這是一個有趣的論點。
您潛在地在並排構建兩個完全不同的系統
ES世界中一個非常常見的建議是, 你不會到處都有事件來源 。這在概念層面上都很好,但實際上通過系統確定在何處以及何時繪製這些架構邊界是非常困難的。
核心原因是,首先導致您進入事件溯源的需求通常不會因為您的應用程式的某些部分很“粗暴”而消失。比如如果您仍需要稽核資料,是否為那些非事件驅動的部件構建了完全不同的稽核策略?或者只是重用已經部署和測試過的分類帳設定?與其他系統通訊怎麼樣?您是否構建了新的通訊渠道,或重用已經存在的流式架構?
沒有明確的答案,因為沒有理想的路徑。每個人都有自己的痛點和退縮。
審計日誌中的以前狀態通常會出現保真度問題
軟體變更,需求變更,重點轉移。那些不可改變的“事實”,以及你處理它們的能力,不會像你期望的那樣持續。
如何處理不相關/錯誤/過時的事件?
您是否將現已棄用的事件保留在分類帳中,但在實現過程中將其“強制轉換”為新事件(或no-ops),還是重寫分類帳本身以刪除/轉換舊事件?這個領域的最佳實踐經常被爭論。
無論你採取哪種方式,一旦你採取它,你就失去了 在重寫時 準確生成系統狀態的能力。
因此,經常出售 “100%準確的稽核日誌” 和 “簡單的時間查詢”的 想法 ! 一旦你超越了概念/玩具舞臺並進入現實世界,最終會遭遇“不”的情況。如果您已將您的魔法日誌創意出售給利益相關者,那麼隨著時間的推移,這種保真度損失可能會出現問題,具體取決於您的領域。
審計日誌通常 過於 繁瑣, 無法 直接使用
對應用程式中的每個操作都有一個完整的低階審計日誌通常更多是一個障礙而不是幫助,意思是,大部分事件都是純粹的噪音(banq注:領域事件與事件溯源的事件應該同一,除此以外的事件是噪音,需要過濾),實際上需要由終端使用者和消費子系統過濾掉。如果您要向終端使用者顯示稽核日誌,那麼離散邏輯狀態通常比瞬態中間體更有價值。因此,“免費審計日誌”實際上變成了“乏味的投影寫入”。對於下游系統,這種混亂導致類似的協調問題。“我應該什麼時候開始跑?” 並且“我應該關心事件X嗎?” 在設計會議期間是一個常見問題。
作為除錯工具的審計日誌被認為:過度炒作
基於分類帳的另一個受歡迎的好處是它有助於除錯。“如果你在應用程式中發現了一個錯誤,你可以重播日誌,看看你是如何進入該狀態的!” 我還沒看到這個戲劇。99%的“壞狀態”是由您的標準普通人為錯誤引起的 不良事件 。在使用標準資料庫集時,使用分類帳對正常除錯直覺幾乎沒有任何價值。意思是,如果某個age欄位已損壞,您可能知道要開始調查的是哪段程式碼。
預測實際上並不是免費的
“你不再侷限於單一的桌面結構”,Event Sourcing說。如果您需要不同的資料檢視,只需以新的方式實現事件日誌。“它是如此容易!”
實際上,這在初始開發成本和持續維護方面都很昂貴。您新增的第一個額外投影會使觸及事件流的程式碼量增加一倍。可能性很大,你會寫出不止一個投影。所以現在你有N個東西處理這個事件流。如果您新增,修改或刪除事件型別,您就可以將該更改的知識傳播到N個不同的位置。
你將處理物化檢視滯後
一旦您的資料增長到無法在合理的時間內從分類帳中實現的程度,您將被迫將讀取解除安裝到物化預測。通過這一步驟實現了物化檢視滯後和讀寫後一致性的損失。
資訊現在要麼過時,要麼丟失,要麼就是錯誤。新建立的資料將為404,刪除的專案將笨拙地貼上,重複的專案將被返回,基本上所有的樂趣都是 最終 的一致性。
單獨來說,它們並不是一件大事,但這些仍然是你必須花時間解決的問題。你是否採用後備策略進行讀取?您是否花時間將智慧新增到物化本身以使其更快?您是否編寫邏輯以允許呼叫者請求他們想要的讀取型別(即,以延遲為代價的分類帳,或以一致性為代價預測)?
有很多方法可以解決它。但 你 必須解決它是我在這裡得到的關鍵。這是需要計算,計劃,實施和部署的時間(所有這些都是您 應該 解決的問題!)。
最後:在你超過玩具水平之前,你不會真正瞭解痛點。
這只是維護任何長期存在的軟體的現實。無論你多少嘗試準備,你做了多少背景閱讀,或者你建立了多少原型,你都在做一些 全新的 事情。導致最痛苦的問題不會在小型測試程式中體現出來。只有你有一個活生生呼吸的機器,依賴你的使用者,你無法拋棄的消費者,以及困擾軟體專案的所有其他現實世界的複雜性都體現在事件溯源中。一旦你碰到他們,你就獨自一人(孤獨面對挑戰)。
所以現在怎麼辦?
事件溯源不是 所有都不行 ,我對它的抱怨就是:它已經瘋狂到作為治癒的所有問題的銀彈,很少有任何負面的副作用報道。我仍然非常喜歡來自事件溯源的 想法 ,只是把它付諸實踐會帶來比我原本想要的更多的痛苦。
我想你通常可以用一些單獨的時間,深刻的反省和兩個問題回答它:
- 哪個 核心問題 是事件溯源解決方案?
- 你真正想要的只是一個普通的舊佇列嗎?
如果你不能具體地回答第一個問題,如果你只是需要“審計”,“靈活性”,或“讀取分離”:就不必使用ES。這些不是通過ES專門解決的問題。
一個好的歷史明細表可以獲得80%的分類賬價值,基本上還沒有任何成本。
同樣,CQRS不需要事件源。您可以擁有不同投影的所有功能, 而無需 將分類帳放在系統的核心位置。
後一個問題是清除像我這樣的迷茫的人,他們認為分類帳會統治世界。檢視系統的互動點,如果您要進行全面的事件溯源,就要研究實際上會產生哪些事件?那些下游系統是否關心那些中間狀態與事件,還是需要過濾的一些不必要的事件噪聲?如果最終目標只是通過 某種方式 進行通訊的分離過程,則不需要事件源。在這兩個壞男孩之間放個佇列就行,那就可以開始享受美好生活。