2011-11-21 23 views
4

我試圖評估EventStore與服務器軟件內部的可靠排隊機制一樣。EventStore事件和其他功能的部分排序

MSMQ作爲替代方式失敗,因爲它不支持部分排序​​,消息「對話」中的有序消息。並且由於其4MB的消息大小限制(可以通過部分排序來克服)。 SQL Service Broker確實支持部分排序​​,但是以編程方式設置和管理是一件痛苦的事情。

由於EventStore上的文檔無疑稀少,有EventStore經驗的人可以使用以下內容嗎?

  • EventStore是否支持事件的事務處理 - 即如果處理失敗, 可以退出出列嗎?
  • 隨着各個線程,進程,或機器多個讀取器, 確實EventStore執行使得每個事件被調度(α)僅一個 讀數器(在一個時間,也許是在事務處理期間)
  • 假設以上是可能的話,不同「對話」上的事件可以以任意順序同時讀取,而同一對話中的消息是 單獨讀取和按順序讀取?
  • 我讀到EventStore基本上是「至少一次」交付。是否可以使用某些存儲提供商 來確保「準確一次」 交付?
  • 「毒藥」事件是如何處理的?在處理過程中發生錯誤的事件。也許 錯誤本質上是暫時的,可以重試。也許它在本質上是永久性的,並且需要行政干預。
  • 如果需要,可以手動操作EventStore存儲嗎? 可以在其他讀者繼續閱讀時完成嗎?

(我讀的存儲引擎的交易不是必需的,但我還是用數據來表示無論在EventStore水平代替交易的語言。如果有,從交易到交換機關鍵功能後果無論如何,請對它們發表評論,我不需要立即瞭解每一個方面,只需要希望與其購買更多的時間來試驗。)

回答

4

儘管EventStore可能被用來構建一個全功能的應用程序,吹起來的隊列,它從來沒有被設計過。這意味着有很多有意見的決定會影響圖書館的建設,違揹你提出的要求。

例如,準確一次傳遞的概念是郵件系統不真正支持的。上面提到的其他東西,比如有毒消息,並不是真正的問題,因爲EventStore沒有以這種方式掛接到消息管道中。

您試圖解決的問題似乎並不是EventStore可以幫助您的問題。因此,我建議評估一個全面的消息隊列,比如RabbitMQ。

此外,你有什麼消息使他們大於4MB?如果您推送文件或大型二進制流,爲什麼不將它們推送到某種高度可用的「全局」存儲(如Amazon S3),然後指向消息中的那些指針?

+0

謝謝!該應用程序適用於服務器協議間保證傳遞消息的服務器,但隊列在應用程序內部,但可以路由任意消息。 S3太多了。外部存儲太複雜。你是說RabbitMQ DOES滿足所有這些要求嗎?謝謝! –

+0

兔子絕對值得關注你的情況,但我不能保證它適合你所提到的一切。 –

4

一些想法,即使你表現出了第一個答案內容:

  • 偏序是,如果你跟蹤消息因果關係會發生什麼。有這樣做的方法。最簡單的做法是簡單地保留分佈式網絡中所有節點的列表,當您推送消息時,給定消息已經看到並添加到該列表中。我說消息,但我真的在提到那個對話中的消息。

    現在,這可能適用於簡單的系統,但隨着您開始獲得更復雜的系統,您可能需要佐賀追蹤哪些消息意味着什麼。

    儘管如此,您可能需要在單個收件人節點上進行部分排序 - 然後以散焦模式處理關於消息流的sagas不會對您有所幫助。那麼也許你實際上需要爲你使用的傳輸添加一些邏輯。

    一種算法被稱爲vector clocks,另一種算法被稱爲version vectors。下面是Go中的矢量時鐘示例實現 - 如果您想要花費幾個小時的配對,我正在爲F#開發一個小矢量時鐘庫 - 因爲算法實際上非常簡單。如果你想真正閱讀一些有意義的東西,我推薦這本書 - Elements of Distributed Systems。第2-3,5章很好。

    然後,您可以在分佈式系統中對部分對話進行排序。之所以無法通過隊列獲得此結果,是因爲您的隊列和節點之間存在大量網絡,並且如果節點或隊列所在的同一節點上的進程因爲有消息而停止在傳輸過程中,此消息將重新排序並重新排序。同樣的事情,如果你沒有消息。你可以通過在隊列和消費客戶端上使用2PC來解決這個重新排序問題,或者你可以通過它們的向量時鐘對消息進行排序,或者你可以按照發布/發送應用程序中給出的序列ID排序它們,或者你可以根據一些數據對它們進行排序,因爲從消費者的角度來看,它具有語義意義。這是你的選擇。

  • 至於其他的要求,這樣一個有害的消息,你應該看看服務總線給你什麼。我個人使用MassTransit,它可以很好地處理毒訊。這些是消費消息的一些失敗模式:

    • 序列化錯誤 - 您犯了編程錯誤。修正你的開發過程,因爲這些不應該發生。如果它們仍然發生,只需將它們移到毒性隊列中 - 這些消息可能已損壞。
    • 從你的代碼中未處理的異常 - 你犯了一個編程錯誤。再一次,你的開發過程正在進行檢查。除非你拋出它,讓服務總線運行時將消息移動到毒性隊列。
    • 您可能會遇到寫入本地消費者數據庫的問題 - 這是一個操作問題,不應在代碼中發生。殺死你的進程,因爲你現在實際上無法從代碼中做任何事情。 Naigos或其他一些流程監視器應該告訴您的操作人員某些事情已經停止並且需要立即解決 - 因爲如果您無法寫入您的讀取模型,那麼您的讀取模型可能無法處理針對它的請求。傀儡或其他進程監視器可能會在一段時間後重啓你的進程,然後你可以通過相同的步驟,假設一切正常,但是這次不要開始消耗掉你的隊列,直到你連接到數據庫(例如NHibernate在啓動時執行靜態初始化),並在該重試邏輯之上實施重試策略,如斷路器。
  • 大事件 - 確保您的隊列API塊字節數組過長。 ZeroMQ具有多部分消息。 AMQP/RabbitMQ還沒有,所以你必須自己組裝,當然,迫使你重新訂購它們。或者你可以在一個可以從其他地方讀取它的地方給出一個二進制位的句柄。

+0

這是一篇優秀的文章。謝謝。我正在閱讀一些關於這些主題的最初研究論文。對於這個項目,我使用NOLOCK,READPAST和比較和交換技術來實現定製的SQL實現,以實現我需要的低爭用基於事務的部分訂單交付。 (兩張表,dbo.Sequences和dbo.Messages)。也許矢量時鐘可以幫助未來的項目,並允許我避免我的實現中存在的廢棄序列的小垃圾收集問題。 –