大多數系統在數據庫存的都是系統的狀態數據,好比一個用戶表可能會存用戶的姓名、頭像、個性簽名等信息。若是隻存狀態數據的傳統模式會有什麼問題呢?sql
假設你公司作了一個系統,並正式上線了。通過一週的推廣,老闆問你要一些用戶的行爲數據。老闆想知道全部用戶平均修改個性簽名的次數。數據庫
對於傳統的數據庫設計,當用戶修改個性簽名,會執行相似以下的 SQL 語句:設計模式
UPDATE Users SET Sign='Talk is cheap, show me the code.' WHERE Id=123
問題是目前數據庫沒有記錄用戶修改密碼次數的字段。因而,爲了更快的實現老闆的需求,你須要給數據庫的用戶表增長這樣一個字段。用戶每次修改個性簽名的時候,這個字段值加一。數據庫設計
這樣雖然很好的解決了問題,但若是這種需求愈來愈多,好比老闆又問你要全部用戶平均修改密碼的次數,就會有一些明顯的問題:學習
上面用戶的個性簽名、密碼修改次數的例子算是簡單的需求,增長字段、修改代碼還能夠應付。但需求稍微變換一下,複雜一點,好比要分析某商品在用戶購物車中變化的狀況,如什麼時間點添加這個商品到購物車的用戶最多、當用戶從購物車移除該商品的同時購物車中有哪些競品等。這種需求帶來的修改,會使數據庫設計和系統變得無比複雜,產生的工做量也是巨大的。測試
可見,隨着系統不斷擴大,業務需求愈來愈多樣化,這種數據庫存儲狀態數據的傳統模式就會愈加捉襟見肘了。設計
面對這種「痛」,事件溯源多是一劑良方。日誌
事件溯源(ES,Event Sourcing),字面上理解就是使任何對數據的修改均可追溯。code
事件溯源是一種設計模式。相對於傳統的在數據庫中存儲系統的狀態,事件溯源在數據庫中存儲的是系統發生的事件。blog
舉個例子,當用戶在系統中註冊後,一個UserCreated
的事件就被存儲了。而後,當用戶修改了密碼,一個UserChangedPassword
的事件就被存儲了。對於這個用戶而言,經過事件溯源設計模式,系統能夠知道該用戶的一舉一動。好比按照時間線,某個用戶的事件多是這樣的:
這樣對於前文用戶平均修改個性簽名次數的需求,就能夠輕鬆應對了。只須要查詢事件爲UserChangedPassword
的數量再除以用戶總數便可。
事件溯源在現實世界中更接近人們的思惟習慣,好比當有人問你今天過得怎麼樣時,你不會告訴他們今天你的體重是多少、吃了幾頓飯(狀態數據),而會告訴他們發生了什麼有趣的事情(事件)。因此對系統來講,也更容易建模。
事件溯源適用於數據分析,能夠生成各類維度的報表,幫助你更深刻地瞭解數據;能夠提供審計日誌,幫助你準確地知道系統是如何從一個狀態變成另外一個狀態的。好比你在銀行存了一千萬,隔了一年後發現帳戶餘額只有一百塊。事件溯源就能夠告訴你,你是如何一步一步從一個千萬富翁變成窮光蛋的。
聽上去不錯,但事件溯源也不是包治百病的萬能藥。
事件溯源會給系統增長額外的複雜性。每每用傳統方式能夠簡單快速完成的增、刪、改功能,使用事件溯源就會多繞幾步。它一般須要與 CQRS (Command Query Responsibility Segregation,命令查詢職責分離) 結合使用,這對開發人員而言,學習成本更高。
若是是不須要審計日誌的小規模系統,使用事件溯源就會得不償失。若是團隊中沒有在這方面有足夠的經驗的開發者,也不要輕易在生產環境中使用它。沒有精鋼鑽,不攬瓷器活。