系統記憶模式:事件溯源的力量,上下文為王! – thenewstack

banq發表於2021-03-30

體現Gof設計模式之忘錄記憶模式的設計不只是事件溯源,還有Git和區塊鏈,分散式賬本就是一種記錄記憶模式,透過備忘錄記憶獲得上下文。
關於領域驅動設計(DDD)、命令查詢責任隔離(CQRS)和事件溯源(ES)的書籍,文章,演講,部落格,影片很多。這三個概念相互補充,因此涵蓋其中一個的幾乎所有資源都至少會提及另外兩個。本文也不例外,但它會嘗試以不同的方式處理問題。代替圖和簡化的程式碼示例,它將為您提供一些類比並幫助您構建一些有用的思維模型,以更好地理解上述概念(尤其是ES)的適用性。
好的電影參考開始怎麼樣?以心理驚悚片“ Memento”為例,其中一個男人努力尋找妻子的兇手。棘手的是,他的病情很重-他無法建立新的記憶。實際上,情況並非完全是虛構的。早在1953年,亨利·莫萊森(Henry Molaison)由於進行腦外科手術而無法形成新的記憶,而腦外科手術本來可以幫助控制他的癲癇病。
想象一下,您知道一切對您正常工作至關重要的東西,但對過去幾天,幾周,幾個月,幾年沒有記憶(包括書面的記憶)。考慮一下它將如何影響您執行每天應執行的任務的能力。無法形成新的記憶,一個人必須完全依靠記憶。
這意味著要根據自己的實際狀態和目前為止周圍環境的當前狀態來做出決策。
 

軟體系統應該有記憶嗎?
似乎很多應用程式只需要知道當前狀態即可正常執行。這就是它們的設計方式。以一個簡單的產品目錄系統為例。告知您現在有哪些產品可用,並向您顯示有關它們的所有詳細資訊,這做得非常好。它不關心產品如何進入目錄或如何以及何時進行修改(除非有審計要求)。
像上述產品目錄這樣的系統無法形成新的記憶。直到有人問:上週有哪些產品可用?無論您如何修改系統,如果沒有記憶,它將無法回答該問題。
可悲的是,當您意識到需要記憶時,擁有記憶已經為時已晚。
實際上大多數軟體系統確實都有一些記憶。我們通常稱它們為日誌。它們實質上是儲存在檔案,資料庫,專用工具等之中。
它們包含有關過去在系統中發生的事情的資訊,這些事情以某種方式或另一種方式是重要的。很難想象沒有某種日誌系統的現代軟體系統。日誌記錄通常對開發人員來說非常無聊,對於維護人員而言,這是額外的工作,通常會被利益相關者所忽視,但是當事情出錯時,它變得無價之寶。
當然,並非所有軟體系統都是以這種方式設計的。您可能會驚訝地發現,關聯式資料庫(某種程度上代表了狀態一致性的系統的標誌性代表)實際上很好地利用了他們自己的記憶。大多數資料庫維護一個事務日誌,該日誌包含導致任何型別的狀態修改的每個過去的事件。客戶端與資料庫互動時根本不使用該事務日誌。但是,在資料複製和資料還原方案中,它是無價的。它允許資料庫節點從任何以前的備份中還原,並透過重新應用備份後發生的事務日誌中的所有事件來建立當前狀態。
 

狀態與記憶的關係
現在讓我們將該概念擴充套件到最初看起來像另一個極端的情況。如何而不是不斷更新一個狀態,而是在每次需要時使用系統的記憶體(事務日誌)從頭開始(重新)構建它?
顯然,對於諸如關聯式資料庫之類的系統而言,這並不是一個非常明智的舉動。處理大量事務並在記憶體中處理TB級資料不僅是一個糟糕的主意。關聯式資料庫具有定義明確,已知的前期和某種通用功能範圍的事實。他們所持有的資料的一致狀態是他們的主要關注點,並且他們對這種狀態如何形成的記憶很難以任何重要的方式豐富正常的操作。
但是其他系統呢?像以業務為中心的應用程式一樣,我們許多人都花費寶貴的時間來構建。我們已經瞭解了記憶如何增強決策和任務完成能力。那些業務應用程式通常就是這樣做的:做出決策並完成任務。賦予他們形成記憶的能力是很有意義的,不是嗎?但是,然後,他們還需要保持狀態嗎?也許不是,因為他們可以根據需要從自己的記憶中確定自己的狀態。
如果您覺得這個主意可笑,請不要放棄。可以肯定的是,大多數人最近很高興地使用它,從前也認為它很可笑。
相反,請嘗試回答以下問題:“現在您的錢包裡有多少錢?” 如果您像大多數人一樣,就不太可能想到這個數字。但是您可能還記得,在某個令人難忘的時間點,您擁有X,然後在另一個令人難忘的時間點,您獲得/花費了Y,甚至在您不知道它之前,您就透過一系列事件構造了錢包的狀態。
一點也不難,不是嗎?請注意,您如何自動並下意識地忽略了在同一時間範圍內收集的但與錢包上下文無關的一堆記憶。恭喜,您剛剛發現自己的想法是Event Sourcing。(有了記憶才有了上下文)
 

上下文是王
嘗試告訴您的團隊(不首先解釋事件來源)有關您計劃從過去的事件中不斷(重新)構建狀態的計劃,他們肯定會擔心您的心理精神問題。那是因為他們可能會考慮整個狀態。隨需應變的重構狀態與將整個資料庫載入到記憶體中的想法一樣令人恐懼。
實際上,與資料庫不同,大多數業務應用程式不需要整個狀態來執行任務。實際上,他們通常只需要其中的一小部分。通常,狀態的這一部分可以透過少數事件來(重新)構造。就像您的大腦裡錢包的狀態一樣。這就是“聚合”(通常是域驅動設計)概念派上用場的地方。
根據定義,聚合它是一個構造塊,將各個領域物件分組在一起並封裝在一起,對於給定上下文中的狀態修改,必須將這些物件視為一個整體。這給您帶來了明確的界限。您只需(重新)生成聚合的狀態即可執行所需的操作。在這種情況下,系統其餘部分的狀態無關緊要。
不需要在每個查詢上從頭開始重新生成整個系統的狀態,對於大多數查詢目的而言,包含某個人可能感興趣的資料的狀態投影(或您希望使用的子集)就足夠了。這就需要“命令查詢責任隔離CQRS”體系結構模式:明確將命令與查詢分開,使應用程式記憶體(事件日誌)成為事實的唯一來源。
 
banq注:體現系統備忘錄記憶模式的設計不只是事件溯源,還有Git和區塊鏈,區塊鏈這種分散式賬本本身就是一種記錄記憶模式,任何一筆交易的上文:前幾筆交易,以及後續下文的幾筆交易都可以透過區塊鏈的鏈資料查詢到,DDD+CQRS+ES是以類似方式實現,思路是一致的,可以使用DDD思路來判斷哪些場合能夠使用區塊鏈技術,這解決了區塊鏈用例場景的判斷問題,區塊鏈本身的加密以及工作證明的複雜性會限制判斷其用途。見下面帖子如何用DDD聚合判斷區塊鏈是否可以使用某個業務場景:

美國紐約州將新冠健康通行證與區塊鏈結合是一種炒作?

lakeFS:實現類似於Git或事件溯源ES的物件儲存功能

 

相關文章