2015 年 9 月

第 30 卷,第 9 期

本文章是由機器翻譯。

技術最前線 - 通用應用程式的事件溯源 (Event Sourcing)

Dino Esposito | 2015 年 9 月

Dino Esposito它是這類一般和自然的活動您可能會不甚至還可提供更以為它。當您將資料儲存體時,自然會考慮只會保留資料的目前狀態的格式。雖然某些大規模的系統,如保險或其中任何軟體的動作會仔細的銀行產業追蹤和記錄儲存目前的資料狀態會比滿足大部分的應用程式和網站。

目前狀態方法會擷取系統狀態的快照集,而且會持續。資料通常位於關聯式資料庫中。這足以進行新交易和擷取的過去的交易結果。過去十年來已還沒有目前的狀態儲存體不足的狀況最常見的。

如今,快速變更的商業樣貌。追蹤商務和網域事件會變得更多的必要性。事件來源 (ES) 是會影響儲存體架構和擷取和插入預存的資料的方式的模式。ES 幾乎不稽核與記錄保存網域中的商務相關的事件。還能使用較低的抽象層來儲存您的資料,並使用實習工具及模式來建立多個資料投影。

ES 看起來會像智慧型也很酷的方式記錄和稽核商務功能,但其實是新的儲存體模型理論上是相關關聯式模型已開始之後。它甚至可能需要更好的影響現代軟體比 NoSQL 儲存體上。ES 不是替代現今的關聯式和 NoSQL 產品。您可以實作 ES 關聯式資料庫和 NoSQL 資料存放區。ES 是有關變更您的創意的應用程式儲存區和資料語彙基元為使用而不可設定狀態之值的事件。

何時事件來源有助於?

超越目前的狀態存放區的基本但常見的方法是追蹤更新歷程記錄。想像一下一個簡單的書店應用程式。描述屬性對每個活頁簿並讓您編輯權限的使用者。應該您追蹤的舊的描述當使用者輸入一個新嗎?

每個人的需求可能會不同,但是想像一下追蹤在此範例中的更新是很重要。會實作這個? 其中一個選項是以儲存目前的活頁簿狀態和記錄在個別的資料表上的任何更新詳細資料。您可以讓每個更新的一筆記錄。更新記錄會包含更新差異,例如每個已修改的資料行的舊的和新值。

您可以也這麼做不同的方式。線上叢書 》 的資料表可能包含多個記錄標示為具有指定 ID 相同的活頁簿每一筆記錄會代表順序列出緊接狀態 (請參閱 [圖 1)。

多筆記錄保存實體歷程記錄
[圖 1 多筆記錄保存實體歷程記錄

此案例需要臨機操作的 API 來讀取目前的記錄狀態。它不是只會選取的記錄識別碼的儲存機制中的查詢您必須挑選具有最新的時間戳記或最高的更新漸進式數目。此外,與指定的資料實體相關聯的所有事件的聯集形成資料流。該事件資料流是 ES 中常用的概念。

ES 協助每當的商業需求在您追蹤一系列的事件。雖然 ES 看起來會像記錄或稽核等跨領域問題,但卻大不相同。但不會記錄事件至設定檔或追蹤例外狀況。它只會追蹤商務事件。而且它不是跨領域問題,但主要適用於儲存體的架構決策。

事件來源定義

簡單的說,ES 是關於使用做為主要資料來源的事件。因此開發人員獨有的問題忽略它數十年 ES 並不一定是普通的應用程式很有用。ES 今天似乎無用、 它多半是因為您不需要尚未。

我要如何彙總 ES 的需求如下: 如果網域專家需要追蹤軟體可能會產生的事件的順序,然後事件來源是可行的選項。否則它可能是事件是對 express 工作流程和串連的商務邏輯組合仍然很實用。在此情況下,不過,事件不是網域中的第一等公民和可能不會保存。這現在是主流的案例。

讓我們看看您當事件是您的應用程式的主要資料來源。ES 會影響儲存體的兩個層面: 持續性和查詢。持續性的特點在於三個核心作業 — 插入、 更新及刪除。在 ES 案例中,插入是與傳統的系統保存目前的實體狀態幾乎相同。系統會接收要求並寫入存放區中的新事件。事件包含唯一識別碼 (例如 GUID)、 型別名稱或識別的事件、 時間戳記和相關聯的資訊類型的程式碼。

更新是由相同的資料實體容器中的另一個插入所組成。新的項目只會反映資料 — 哪些屬性已變更,新的值和相關商務網域中,如果如何和為什麼它變更。一旦執行更新之後,資料存放區的發展,如所示 [圖 2

新的記錄表示實體的 ID #1 更新
[圖 2 新記錄表示實體的 ID #1 更新

刪除作業的運作方式與 Update 相同除了它有不同的資訊讓很明顯是一項刪除作業。

立即進行這類更新會造成一些問題談到查詢。您怎麼知道是否不存在指定的記錄或目前的狀態可能是? 需要查詢在概念上選取具有相符識別碼的所有記錄然後分析資料集事件的事件之後的臨機操作層。

例如,它可以建立新的資料實體建立事件內容為基礎。然後它會重新執行所有後續的步驟並傳回什麼會保持為資料流結尾。這項技術稱為事件重新執行。一般的重新執行要重建狀態的事件可能會引發一些考慮到效能。

請思考銀行帳戶。開啟銀行帳戶年前的客戶會累積此後數百個作業以及事件。若要取得目前的平衡,您必須重新執行來重建目前的帳戶狀態的數個數百個作業。這可能不是永遠可行。

有這種情況下的因應措施。最重要組成建立快照集。快照集是將實體的已知的狀態儲存在指定時間的記錄。如此一來,就不需要重新執行快照集之前且帶有生效日期的事件。

ES 不受限於任何技術或產品是否為特定的關聯式資料庫或 NoSQL 資料存放區。ES 不會引發至少一種特殊的軟體元件的需求 — 事件存放區。事件存放區是基本上是事件記錄檔。您可以建立一個在您選擇的任何資料存放區 API 之上使用自己的程式碼。

事件存放區都有兩個主要的特性。首先和最重要是僅限附加的資料存放區。它並不支援更新並可選擇性地支援只有特定類型的刪除。第二,事件存放區必須能傳回與指定的索引鍵相關聯的事件資料流。您可以自行建立此一層程式碼或使用可用的工具和架構。

事件存放區選項

您可以實作的運作方式的事件存放使用任何項目。它通常會使用關聯式資料庫或 NoSQL 資料存放區的部分類別做為持續性引擎。如果您打算使用關聯式資料庫,您可以產生每個事件的一個資料列的實體類型的每一個資料表。

事件通常會有不同的配置。例如,每個事件可能有不同數目的屬性來儲存,因而難以找出通用的結構描述的所有資料列。如果通用的結構描述所產生的所有可能的資料行的聯集甚至可以和執行水平時,這是一個簡單的選項來實作。

否則,您可以查看到 SQL Server 2014 設定資料表來儲存資料而不是水平列的垂直資料行中的資料行索引存放區功能。適用於任何版本的 SQL Server 的另一個選項是正規化為 JSON 物件的事件屬性並將它儲存成單一資料行中的字串。

中 NoSQL 術語 「 文件 」 是具有多個屬性的物件。某些產品中 NoSQL 特製化中儲存文件。從開發人員的觀點來看,它很方便。建立類別、 填入值,並儲存它以現況。類別的型別是索引鍵連結多個事件的資訊。如果您使用 NoSQL,然後只是有個事件的物件並將其儲存。

進行中的專案

ES 是相對較年輕的架構方法。仍然新興的協助撰寫程式碼以事件為基礎的資料存放區上的標準工具。您可以明確地排列自己 ES 方案但臨機操作的一些工具可協助您更結構化的方式處理事件的儲存體。

使用事件感知資料存放區的主要優點是方法的類似資料庫的工具可確保您只能執行讀取和附加方式可以保證商務一致性的事件來源中的事件的動作。一個是專為儲存事件是 NEventStore 專案的架構 (neventstore.org)。這可讓您寫入和讀取後的事件,並持續性的獨立運作。以下是您儲存事件的方式:

var store = Wireup.Init()
  .UsingSqlPersistence("connection")
  .InitializeStorageEngine()
  .UsingJsonSerialization()
  .Build();
var stream = store.CreateStream(aggregateId);
stream.Add(new EventMessage { Body = eventToSave });
stream.CommitChanges(aggregateId);

若要讀取回事件、 開啟資料流和認可事件的集合執行迴圈。

事件存放區 (geteventstore.com) 是藉由提供純 HTTP 與.NET 的應用程式開發介面的事件資料流的運作方式的另一個。ES 術語中彙總等同於存放區中的資料流。您可以執行三個基本的作業上的事件資料流: 寫入事件。讀取的最後一個事件、 特定的事件和甚至配量的事件。與訂閱以取得更新。

有三種類型的訂閱。其中一個是暫時性的也就是說事件寫入指定的資料流叫用回呼函式會叫用每一次。另一個是更新,表示您會收到通知的每個事件開始從一份給定和之後的任何新加入的事件存放區中。最後,永久性訂閱解決案例當多位取用者會等候處理的事件。訂閱可確保事件傳遞至取用者至少一次,但可能會多次且無法預期的順序。

總結

事件 Sourcing 使用做為應用程式資料來源的事件。您不設計架構應用程式將最後已知狀態的實體,但相關的商務事件清單。事件資料來源會儲存資料的抽象等級較低。您需要套用交易與查詢所需的實際實體狀態會從該處來到的投影。投射是重新執行事件並執行某些工作的程序。最明顯的投影所建置的目前狀態。但是您可以有任何數目或類型投影從事件。


Dino Esposito 的共同著作"Microsoft.NET: 構建企業應用程式"(微軟出版社,2014年) 和"程式設計ASP.NETMVC 5"(微軟出版社,2014年)。Microsoft.NET Framework 與在 JetBrains 的 Android 平台和經常在世界各地的產業活動演講的技術推廣人員 Esposito 分享他在軟體的願景software2cents.wordpress.com 和在 Twitter 上 twitter.com/despos

感謝以下技術專家對本文的審閱: 喬恩 · Arne Saeteras