2016-03-01 40 views
0

我想確保某些類型的消息不會丟失,因此我應該使用Confirms (aka Publisher Acknowledgements)如果發佈者在收到ack之前終止,會發生什麼情況?

如果代理在所述 消息寫入磁盤之前崩潰,代理將丟失持久消息。在某些情況下,這會導致經紀人以令人驚訝的方式行事。

例如,請考慮以下情況:

  • 客戶端發佈的持久消息持久的隊列
  • 客戶端從隊列中消耗消息(指出消息是持久性和隊列耐用) ,但尚未確認,
  • 代理程序死亡並重新啓動,並且
  • 客戶端重新連接並開始消費消息。

此時,客戶可以合理地認爲消息 將再次遞送。情況並非如此:重新啓動導致代理丟失信息 。爲了保證持久性,一個 客戶端應該使用確認。

但是,如果使用確認,發佈者在收到確認之前發生故障,並且由於某種原因(即網絡故障)未將消息傳遞到隊列中會怎麼樣。

假設我們有一個簡單的REST端點,我們可以發佈新的COMMENTS,並且當創建一個新的COMMENT時,我們想要在隊列中發佈消息。 (注意:如果我發送一個新的COMMENT消息,但最後由於回滾而未創建消息,則無關緊要)。

CommentEndpoint { 

    Channel channel; 

    post(String comment) { 
    channel.publish("comments-queue",comment) // is a persistent queue 
    Comment aNewComment = new Comment(comment) 
    repository.save(comment) 
    // what happens if the server where this publisher is running terminates here ? 
    channel.waitConfirmations() 
    } 

} 

當服務器重新啓動時,通道消失,消息永遠無法傳遞。 我想到的一個解決方案是,在重新啓動後,查詢庫中最近的註釋(類似於崩潰前最後3分鐘創建的註釋?),併爲每個註釋發送一條消息並等待確認。

回答

1

你擔心的是真的不再是RabbitMQ唯一的問題,它是一個distributed transaction問題。這discussion給出了一個合理的輕量級解決方案。還有更嚴格的解決方案,例如兩階段提交,三階段提交等,以確保數據在真正需要時保持一致。

相關問題