0

我有一個應用程序,其中多個用戶可以發送REST操作來修改共享對象的狀態。 修改對象時,會發生多個操作(數據庫,審計,日誌記錄...)。卡夫卡驗證有狀態處理消息

並非所有操作都是有效的,例如,您不能在刪除對象後修改它。

使用卡夫卡我在想下面的架構:

  1. 休息操作排隊卡夫卡話題。
  2. 對同一對象的操作將進入同一分區。因此,所有的對象的操作將在序列和由消費者
  3. 消費者聽分區處理,使用內存數據庫
  4. 確認操作如果操作是有效的,那麼被髮送到一個「有效操作主題」 otherways被髮送到‘無效操作主題’
  5. 其他消費者(DB,日誌,審計)正在收聽的‘有效操作主題’

我不是很肯定點3號。 我不喜歡保持所有對象狀態的想法。 (我有數十億的對象,即使一個對象可以是10MB的大小,我需要存儲以驗證其狀態只有幾K字節...

但是,這是一種常見模式嗎?否則,你如何驗證某些操作的有效性?

另外你會用什麼作爲內存數據庫?它必須是高度可用的,容錯和支持事務(讀寫)。

+0

我正在考慮使用此:https://samza.apache.org/learn/documentation/0.7.0/container/state-management.html ... –

回答

4

我相信這是一個非常有效的模式,實質上是對事件源CQRS模式的變體。

例如,Lagom implements their CQRS persistence in a very similar fashion(雖然基於完全不同的工具集)

的幾點:

  • 你是正確的關於需要序貫操作:因爲所有的狀態突變,需要根據前一次突變的結果,在執行過程中必須有強大的順序。對於這種情況通常是這種情況,所以我們希望能夠儘可能水平地擴展這些操作,使得每個序列操作都與其他許多序列並行發生。在你的情況下,我們有一個這樣的序列每個共享對象。
  • 依靠Kafka按鍵進行分區是實現該目的的一種好方法(假設您未將max.in.flight.requests.per.connection設置爲高於默認值1)。在這裏,Lagom也有一個類似的方法,讓它們的持久實體分佈並且是單線程的。我不是說Lagom更好,我只是安慰你,其實這是被其他人使用的方法:)

  • 你的模式的一個關鍵方面是將命令轉換爲事件:行話命令被視爲影響國家的請求,並可能由於各種原因被拒絕。事件是對過去發生的狀態更新的描述,並且從接收它的人的角度來看是無可辯駁的:事件總是說實話。你描述的過程將是一個處於兩者邊界的控制器:它負責將命令轉換爲事件。

  • 從這個意義上講,您提到的「有效操作主題」將是您的過程的狀態更新的事件源描述。因爲它全部由卡夫卡支持,所以它可以任意分割,因此可以擴展,這真是太棒了:)
  • 不要擔心所有對象的大小,它必須以某種方式坐在某個地方。既然你有這個控制器把命令轉換成事件,這個控制器成爲與該對象有關的主要真相源,並且這個控制器負責存儲它:這個控制器處理你的事件的主存儲器,所以你必須將空間它。你可以使用Kafka Streams's Key value store:那些對你的每個處理實例都是本地的,但是如果你使它們持久化,它們在處理可用RAM的數據方面沒有問題。由於RocksDB,現場數據泄漏到磁盤上,甚至更多的幕後故事都來自於事件源,因此您的州商店被複制,並且如果需要將在另一臺機器上透明地重新創建

我希望這可以幫助您最終確定您的設計:)