5

嗨,我有以下塞納里奧我不明白如何讓最終一致性:域事件和版本沒有CQRS

  1. 用戶1使用基於任務的用戶界面更改客戶名稱
  2. 應用服務調用操作上上客戶名稱骨料
  3. 骨料火災事件改變
  4. 總線使用nservicebus
  5. NServicebus服務裸片發送消息
  6. 用戶2得到聚集,並呼籲改變地址
  7. 聚合操作稱爲
  8. 域觸發的事件
  9. 信息放在總線
  10. 客車重新啓動
  11. 消息2拿起第一
  12. 消息2處理等有限上下文更新了新地址
  13. 消息1現在拿起這是錯誤的訂單
  14. 現在會發生什麼

如果我們在事件中傳遞聚合的版本,那麼13中會有樂觀的併發錯誤嗎?

如果是這樣,消息1新獲取應用於其他上下文中的對象。我們如何保持一致?

這是阻止我在我的域中應用事件的問題。所有幫助歡迎。

基本的想法是在另一個上下文中更新另一個聚合。我只是停留在這個併發技術上。

在命令處理程序和命令按下總線的意義上,我們不使用事件源或CQRS。只有我們想要異步發生的事件處理,因爲我們有一個我們不希望改變的現有設計。

Blair

回答

3

通常你會排隊消息。如果他們進入隊列,您將得到正確的排序。如果你想使用不支持與你的服務總線排序的東西,那麼在你的事件中添加一個序列號,這樣對方可以正確地對它們進行重新排序。 TCP一直在做這個自1981年以來http://www.ietf.org/rfc/rfc793.txt :)

+0

我不確定你的意思。我通過nservicebus發送活動,所以沒有訂購。如果我爲我的事件添加序列號,我該如何在另一端執行排序?我錯過了什麼,一定有什麼明顯的我沒有看到。 – 2013-03-02 12:17:15

+0

也有NServicebus與多個線程不保證他們將按順序處理。 – 2013-03-02 12:19:59

+0

跟蹤另一端的序列號。在序列號匹配'最後處理的序列號+ 1'之前不要處理該消息。 – 2013-03-02 12:21:09

0

哎呀:我剛纔注意到你實際上是在你的榜樣(客戶名稱,然後客戶地址)使用2級不同的任務。當然,這不是問題,因爲訂單確實不重要。但我會留下我的回答,以防萬一你的意圖是有兩個相同類型的變化。

一如往常幾個問題/問題浮現在腦海中:

一件事你的例子並不需要一個端點失敗,因爲用戶可以更新在同一時間的地址和處理的順序可以是隨機的。所以問題變成了哪一個是正確的地址。所以解決需要更多的分析。對於一兩件事,我想我們可以假設一個客戶不動非常頻繁,2個用戶在同一時間更新地址(甚至在它附近)--- :)

即使如此,也許是第一個地址是正確的。

我認爲要確定是否併發性,甚至一些其他的容忍這樣的情況,是一個問題。所以也許地址只能每天更換一次,其他任何更改都需要其他互動。所以一些異常處理是一個選項。

你真的不應該走這歸因於技術層面,試圖解決它,而是看過程/業務的影響。

對於一個簡單的解決方案,我將與匹配的消息發送去日期到最後一次操作日期爲特定類型。因此,對於ChangeAddressCommand處理郵件時,您可以將其與當前的LastAddressChange進行比較,如果郵件是在最後更改日期之前發送的,則拒絕該郵件。

0

類似issuee與NServiceBus討論here。 OP建議使用IBus.HandleCurrentMessageLater()旋轉,直到其他消息到達。這可以工作,但可能會有問題,因爲你永遠不知道你需要等多久。

一個更復雜的選擇是使用saga這將等到領導到一個特定版本的所有消息已經到達。在這種情況下,排序是基於版本進行的,並且只有在彙總版本中的所有更改都發布到其他BC時纔有可能。假設消息1在彙總的版本2上運行。然後它增加聚合的版本併發佈一個事件,說明它在版本2上運行。消息2在聚合的版本3上運行,併發佈一個事件,說明它在版本3上運行。當另一個BC中的NServiceBus端點在消息1之前接收消息2,它知道最後收到的消息在聚合的版本1上運行,所以它需要一個在版本2上運行的消息。它將啓動等待下一消息的傳奇。一旦接收到消息1,該傳奇將應用消息1,然後消息2並釋放傳奇狀態。如果使用版本進行測序是不可接受的,則可以使用另一種測序策略。

0

根據this你應該問自己:

什麼是有故障對業務的影響?

在你目前的情況下,你有這個問題一次一百萬個請求。如果您接受這兩個請求都是有效的,我認爲它不會對業務產生巨大影響。