輕鬆應對並發問題,Newbe.Claptrap 框架中 State 和 Event 應該如何理解?
- 2020 年 7 月 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 正確性的重要參數。因此,需要確保事件被永久保存。但,這不是絕對的情況,如果滿足以下條件,那麼事件就允許被丟失:
- 在丟失事件之前存在一個永久的 State 快照
- 對應的 Claptrap 已經生命終結,永遠都不會再被激活
反之,如果不滿足以上的條件,那麼請必須確保在生產環境中的事件被正確的保存在持久化層,並且已經有相應的容災手段。
狀態 State
State 在 Actor 模式中代表了 Actor 對象當前的數據表現。而在 Claptrap 僅僅只是在此之上增加了一個限制:「State 只能通過事件溯源的方式進行更新」。由於事件溯源的可靠性。Claptrap 中的 State 也就擁有了更好的可靠性。
State 的版本號。在 Claptrap 中的 State 中有一個名為 Version 的屬性,它表示 State 當前的版本。版本號是一個從 0 開始的自增數字,會在每次處理一個事件之後進行自增。
版本號為 0 的 State 是 Claptrap 的初始狀態,也可以被稱為創世狀態。初始狀態可以根據業務需要進行訂製。
Claptrap 和 Minion 對於版本號的處理也有一些區別。
對於 Claptrap 而言,Claptrap 是事件的生產者,因此,事件的版本號本身就是由 Claptrap 進行賦予的。例如,在一次事件的處理過程中,以下這些事情將會依次發生:
- State Version = 1000
- 開始處理 Event ,其 Version = State Version + 1 = 1001
- Event 處理完畢,更新 State Version = 1001
對於 Minion 而言,由於它是 Claptrap 事件的消費者。因此版本號的處理略有不同。例如,在一次事件的處理過程中,以下事件將會依次發生:
- State Version = 1000
- 讀取到了 Event Version 為 1001 的事件
- Event 處理完畢,更新 State Version = 1001
State 的版本號和 Event 的版本號相互依存,相互驗證,是事件有序性的關鍵。如果在處理過程中,出現 State 的版本號和 Event 的版本號不匹配的情況,將會是嚴重的問題。通常來說,出現版本號不匹配,只有兩種情況:
- 持久化層中的事件出現了丟失
- 框架惡性 BUG
最後但是最重要!
最近作者正在構建以反應式
、Actor模式
和事件溯源
為理論基礎的一套服務端開發框架。希望為開發者提供能夠便於開發出 「分散式」、「可水平擴展」、「可測試性高」 的應用系統 ——Newbe.Claptrap
本篇文章是該框架的一篇技術選文,屬於技術構成的一部分。如果讀者對該內容感興趣,歡迎轉發、評論、收藏文章以及項目。您的支援是促進項目成功的關鍵。
聯繫方式:
- Github Issue
- Gitee Issue
- 公開郵箱 [email protected] (發送到該郵箱的內容將被公開)
- Gitter
- QQ 群 553474855
您還可以查閱本系列的其他選文:
理論入門篇
- Newbe.Claptrap – 一套以 「事件溯源」 和 「Actor 模式」 作為基本理論的服務端開發框架
- Newbe.Claptrap 項目周報 1 – 還沒輪影,先用輪跑
- Newbe.Claptrap 框架中為什麼用 Claptrap 和 Minion 兩個詞?
實現入門篇
樣例實踐篇
其他番外篇
- 談反應式編程在服務端中的應用,資料庫操作優化,從 20 秒到 0.5 秒
- 談反應式編程在服務端中的應用,資料庫操作優化,提速 Upsert
- 十萬同時在線用戶,需要多少記憶體?——Newbe.Claptrap 框架水平擴展實驗
- docker-mcr 助您全速下載 dotnet 鏡像
術語介紹篇
GitHub 項目地址://github.com/newbe36524/Newbe.Claptrap
Gitee 項目地址://gitee.com/yks/Newbe.Claptrap
您當前查看的是先行發佈於 www.newbe.pro 上的部落格文章,實際開發文檔隨版本而迭代。若要查看最新的開發文檔,需要移步 claptrap.newbe.pro。
- 本文作者: newbe36524
- 本文鏈接: //www.newbe.pro/Newbe.Claptrap/Event-And-State/
- 版權聲明: 本部落格所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!