輕鬆應對併發問題,Newbe.Claptrap 框架中 State 和 Event 應該如何理解?

Newbe36524發表於2020-07-27

Newbe.Claptrap 框架中 State 和 Event 應該如何理解?最近整理了一下專案的術語表。今天就談談什麼是 Event 和 State。

Newbe.Claptrap 是一個用於輕鬆應對併發問題的分散式開發框架。如果您是首次閱讀本系列文章。建議可以先從本文末尾的入門文章開始瞭解。

事件 Event

Claptrap 是基於事件溯源的 Actor 模式。事件自然就起到了至關重要的作用。

想要操作 Claptrap 就需要對其傳遞事件。事件也是改變 Claptrap State 的唯一引數。因此,在使用 Claptrap 構建系統時,所有的系統操作都會轉換為事件而傳入到 Claptrap 中。事件具有以下這些特點:

事件是有序的

每個事件都包含有一個唯一的序列號。在本框架中,這個序列號被稱為版本號(Version)。事件的版本號是一個從 1 開始逐 1 遞增的序列。事件的有序性,確保了狀態的計算不存在併發問題。這是狀態資料可靠性的重要保證。

事件的有序性直接反應了 Claptrap 執行事件的先後順序。而由於需要確保這種順序,Claptrap 在執行事件時,必須逐個事件進行處理。這點恰好與 Actor 模式的單執行緒特性產生了天然的契合。

事件是不可變的

事件一旦產生,它就是不可變的。事件溯源,正由於事件的不可變性,才使得資料是可靠的。因為只要讀取事件,就能夠還原出任何一個事件執行之後的狀態。但不可變性並不是物理上的限制。你仍然可以修改物理儲存中的事件資料。但請注意,這是危險的,極為不建議的行為。

讓我們聯絡設計模式中的 “開閉原則”,經典的可以被概括為 “對擴充套件開放,對修改封閉”。其中為什麼要強調 “對修改封閉” 呢?就筆者看來,對修改封閉的原因其實是因為修改所帶來的未知性。因為過往執行的程式碼,產生的資料。他們都已經形成了一定的封閉性。他們是經過已有的測試所驗證的。如果嘗試修改他們,勢必就需要調整相應的測試,而這就更進一步加劇了修改,這可不是一件好事。事件的不可變是一種性質,更是一種要求。

那如果由於一個 BUG 導致了過往的產生事件資料不正確,現在需要修正這個 BUG,該怎麼辦呢?筆者的建議,不要嘗試修改已有的事件。應該追加新的事件和演算法來修正當前的狀態。不要去調整舊的內容。筆者認為這更符合開閉原則。開發者可以自行斟酌。

事件是永久的

事件是確保 Claptrap State 正確性的重要引數。因此,需要確保事件被永久儲存。但,這不是絕對的情況,如果滿足以下條件,那麼事件就允許被丟失:

  1. 在丟失事件之前存在一個永久的 State 快照
  2. 對應的 Claptrap 已經生命終結,永遠都不會再被啟用

反之,如果不滿足以上的條件,那麼請必須確保在生產環境中的事件被正確的儲存在持久化層,並且已經有相應的容災手段。

狀態 State

State 在 Actor 模式中代表了 Actor 物件當前的資料表現。而在 Claptrap 僅僅只是在此之上增加了一個限制:“State 只能通過事件溯源的方式進行更新”。由於事件溯源的可靠性。Claptrap 中的 State 也就擁有了更好的可靠性。

State 的版本號。在 Claptrap 中的 State 中有一個名為 Version 的屬性,它表示 State 當前的版本。版本號是一個從 0 開始的自增數字,會在每次處理一個事件之後進行自增。

版本號為 0 的 State 是 Claptrap 的初始狀態,也可以被稱為創世狀態。初始狀態可以根據業務需要進行定製。

Claptrap 和 Minion 對於版本號的處理也有一些區別。

對於 Claptrap 而言,Claptrap 是事件的生產者,因此,事件的版本號本身就是由 Claptrap 進行賦予的。例如,在一次事件的處理過程中,以下這些事情將會依次發生:

  1. State Version = 1000
  2. 開始處理 Event ,其 Version = State Version + 1 = 1001
  3. Event 處理完畢,更新 State Version = 1001

對於 Minion 而言,由於它是 Claptrap 事件的消費者。因此版本號的處理略有不同。例如,在一次事件的處理過程中,以下事件將會依次發生:

  1. State Version = 1000
  2. 讀取到了 Event Version 為 1001 的事件
  3. Event 處理完畢,更新 State Version = 1001

State 的版本號和 Event 的版本號相互依存,相互驗證,是事件有序性的關鍵。如果在處理過程中,出現 State 的版本號和 Event 的版本號不匹配的情況,將會是嚴重的問題。通常來說,出現版本號不匹配,只有兩種情況:

  1. 持久化層中的事件出現了丟失
  2. 框架惡性 BUG

最後但是最重要!

最近作者正在構建以反應式Actor模式事件溯源為理論基礎的一套服務端開發框架。希望為開發者提供能夠便於開發出 “分散式”、“可水平擴充套件”、“可測試性高” 的應用系統 ——Newbe.Claptrap

本篇文章是該框架的一篇技術選文,屬於技術構成的一部分。如果讀者對該內容感興趣,歡迎轉發、評論、收藏文章以及專案。您的支援是促進專案成功的關鍵。

聯絡方式:

您還可以查閱本系列的其他選文:

理論入門篇

  1. Newbe.Claptrap - 一套以 “事件溯源” 和 “Actor 模式” 作為基本理論的服務端開發框架
  2. Newbe.Claptrap 專案週報 1 - 還沒輪影,先用輪跑
  3. Newbe.Claptrap 框架中為什麼用 Claptrap 和 Minion 兩個詞?

實現入門篇

  1. Newbe.Claptrap 框架入門,第一步 —— 建立專案,實現簡易購物車
  2. Newbe.Claptrap 框架入門,第二步 —— 簡單業務,清空購物車

樣例實踐篇

  1. 構建一個簡易的火車票售票系統,Newbe.Claptrap 框架用例,第一步 —— 業務分析

其他番外篇

  1. 談反應式程式設計在服務端中的應用,資料庫操作優化,從 20 秒到 0.5 秒
  2. 談反應式程式設計在服務端中的應用,資料庫操作優化,提速 Upsert
  3. 十萬同時線上使用者,需要多少記憶體?——Newbe.Claptrap 框架水平擴充套件實驗
  4. docker-mcr 助您全速下載 dotnet 映象

術語介紹篇

  1. Actor 模式
  2. 事件溯源(Event Sourcing)
  3. Claptrap
  4. Minion
  5. 事件 (Event)
  6. 狀態 (State)

GitHub 專案地址:https://github.com/newbe36524/Newbe.Claptrap

Gitee 專案地址:https://gitee.com/yks/Newbe.Claptrap

您當前檢視的是先行釋出於 www.newbe.pro 上的部落格文章,實際開發文件隨版本而迭代。若要檢視最新的開發文件,需要移步 claptrap.newbe.pro

Newbe.Claptrap

 

相關文章