翻譯:為什么 Kafka 不適合做 Event Sourcing

原文地址:https://medium.com/serialized-io/apache-kafka-is-not-for-event-sourcing-81735c3cf5c
作者:Jesper Hammarb?ck
在學(xué)習(xí) Event Sourcing 相關(guān)知識(shí)的時(shí)候,發(fā)現(xiàn) Kafka 對消息持久化的方式特別適合 Event Sourcing,在查閱資料過程中發(fā)現(xiàn)早有前人討論了這個(gè)設(shè)想。
非英語專業(yè),文章偏向意譯,不準(zhǔn)確的地方請多包涵。

Kafka 作為一個(gè)消息中間件是一個(gè)非常好的工具,同時(shí)對 topic 持久化的能力讓你可以永久————如果你希望的話————將 messages 保存下來。(the optional topic durability allows you to store your messages permanently)

因此,如果你的 messages 是 event 的話,你可以使用 kafka 來做 event store 或者 event log,但是它真的不是一個(gè)做 event sourcing 的好工具。

下面將講述理由。

加載實(shí)體當(dāng)前狀態(tài)(Loading current state)

當(dāng)一個(gè)服務(wù)接受一個(gè) command,要求改變一個(gè)使用了具有事件溯源的實(shí)體(event sourced entity),我們首先要重建這個(gè)實(shí)體的當(dāng)前狀態(tài)。我們通過從 event store 中加載特定實(shí)體 ID 的所有事件并重新應(yīng)用我們的實(shí)體(的初始狀態(tài)),得到了實(shí)體的當(dāng)前狀態(tài)。

(但是)獲取某個(gè)特定實(shí)體的所有 event 并非一件易事,Topic 通常以各種實(shí)體類型(如 “Orders”、“Payments”、“Notifications”)集中并分區(qū)(centered around and partitioned),因此我們必須要遍歷所有“Orders”的所有 event,去獲得某個(gè)特定的實(shí)體的當(dāng)前狀態(tài)。盡管這是可行的,卻不實(shí)際。

一個(gè)代替方案是一個(gè)實(shí)體擁有一個(gè) topic,但是這樣我們就將面臨成千上萬的 topic,并且更困難的是,下游的訂閱服務(wù)(譯者:消費(fèi)者)需要自動(dòng)發(fā)現(xiàn)承載一個(gè) entity 的最新的 topic。同樣的,不實(shí)際。

寫入一致性 (Consistent writes)

當(dāng)我們的實(shí)體重建了,這時(shí)候該執(zhí)行剛剛接受的 command 所包含的業(yè)務(wù)邏輯了。如果業(yè)務(wù)邏輯失敗,我們會(huì)向客戶端返回一個(gè) error,如果成功,將會(huì)提交一個(gè)新的 event。這樣,我們就必須保證不能有同一個(gè)實(shí)體的別的 event 同時(shí)保存到我們的 event store 中去,否則我們將承擔(dān)破壞我們領(lǐng)域?qū)ο蟮囊恢滦浴?/p>

用 OCC 進(jìn)行補(bǔ)救 (OCC to the rescue)

一個(gè)保證寫入一致性的方法是運(yùn)用 event store 的 optimistic concurrency control。一個(gè)像樣的 event store 應(yīng)當(dāng)讓用戶做出 “保存這個(gè) event 當(dāng)且僅當(dāng)這個(gè)實(shí)體的版本仍然是 x” 這種控制。Kafka 并不支持這個(gè)(<這里的引用是KAFKA-2260,在18年的時(shí)候有個(gè)大哥寫了個(gè)comment說這里已經(jīng)解決這個(gè)問題>),該領(lǐng)域?qū)<医ㄗh的解決方法似乎是在之前放置一個(gè)“數(shù)據(jù)庫”以提供一個(gè)一致性點(diǎn)。盡管此建議在某些情況下可能是可行的解決方案,但從長遠(yuǎn)來看,選擇更適合特定問題的工具可能更明智。

單一寫入 (Single-writer)

另一個(gè)保證一致性的方法就是保證順序?qū)懭?,比如使?single-writer principle,意思就是,我們保證所有某個(gè) id 的實(shí)體的寫入都會(huì)在同一個(gè)線程發(fā)生。我們可以通過保證生產(chǎn)者(producer)同時(shí)是自己的消費(fèi)者(consumer),從而有效地阻塞該 event,直到該 event 提交并在 Kafka 的另一端可用。這種設(shè)計(jì)會(huì)對性能產(chǎn)生嚴(yán)重影響,尤其是考慮到上面談到有限的加載實(shí)體的功能。

究竟合不合適 (Does it fit at all?)

所以,一個(gè) event sourcing 的系統(tǒng)設(shè)計(jì)中能容下 Kafka 嗎?也許??赡?。作為將事件傳輸?shù)较掠尾樵兎?wù)或讀取模型的一種方式,它可能是對事件存儲(chǔ)的一個(gè)很好的補(bǔ)充。

但是,在向我們的系統(tǒng)中添加大型而復(fù)雜的基礎(chǔ)架構(gòu)時(shí),我們應(yīng)始終謹(jǐn)慎————一切都是有代價(jià)的,因此請確保它足以應(yīng)付當(dāng)前的問題!

如果您想開始做 event sourcing,而且你重視 HTTP 的簡單性并欣賞 hosted service,請看一下我們在 Serialized(譯者:稍微看了一下,貌似是一個(gè) Event Store)所做的工作。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容