我有一個應用程序需要將某些數據存儲在數據庫(例如mysql)中,然後在消息隊列中發佈一些數據。我的問題是:如果應用程序在數據庫中存儲後崩潰,我的數據將永遠不會寫入消息隊列,然後丟失(因此我的系統的最終一致性將不會保證)。 我該如何解決這個問題?與數據庫和消息隊列記錄的最終一致性
回答
我有一個應用程序,我需要在數據庫中存儲一些數據(例如mysql),然後在消息隊列中發佈一些數據。我的問題是:如果應用程序在數據庫中存儲後崩潰,我的數據將永遠不會寫入消息隊列,然後丟失(因此我的系統的最終一致性將不會保證)。我怎麼解決這個問題 ?
在這種特殊情況下,答案是從數據庫加載隊列數據。
也就是說,您需要在用於寫入數據的同一事務中將需要排隊的消息寫入數據庫。然後,異步地從數據庫中讀取數據,並將其寫入隊列。
查看Reliable Messaging without Distributed Transactions,作者:Udi Dahan。
如果應用程序崩潰,恢復很簡單 - 在重新啓動過程中,您將查詢數據庫中所有未確認的消息,然後再次發送它們。
請注意,此設計真的希望消息的消費者被設計爲at least once delivery。
非常有用的視頻。但是我很驚訝沒有已知的庫正在執行該流程的「部分」 – ayorosmage
還需要支持事務的數據庫。因此我認爲像mongodb這樣的nosql數據庫不能用於此目的。 – ayorosmage
應該有域名事件是冪等的嗎?是否使用非冪等域事件實現最終一致性的其他變體? – xfg
這太長了評論。
我假設你有一個無損的消息隊列,一旦你得到了寫入數據的確認,隊列就會保證有記錄。
基本上,您需要一個循環來處理可以回滾的事務或數據庫中的狀態。對交易僞代碼:
- BEGIN TRANSACTION
- 插入到數據庫
- 寫入到消息隊列
- 當消息隊列確認,提交事務
就個人而言,我可能會做一個狀態:
- 插入到數據庫的「待定」狀態(或類似的東西)
- 寫入到消息隊列
- 當消息確認,更改狀態爲「已提交」(或類似的東西)
在從失敗中恢復的情況下,您可能需要檢查消息隊列以查看是否有任何「待處理」記錄實際寫入隊列。
謝謝您的回答跟蹤器,我仍然有一些問題: 1)如果我在提交事務之前寫入消息隊列,隊列中的消息可能會在事務提交之前被處理。 2)如果我的ID是由數據庫生成的,我不能將它包含在發佈在隊列中的消息中。 – ayorosmage
添加到@Gordon Linoff所說的假設持久消息(類似於MSMQ?)方法/處理程序將是事務性的,所以如果全部成功,消息將寫入隊列並將數據寫入您的查看模型,如果失敗,所有將失敗...
爲了減輕身份證問題,您將需要使用GUID而不是數據庫生成的密鑰(如果您使用消息傳遞,則需要移除參照完整性並引入GUIDS作爲鍵)。
還有一個建議,不要更新數據庫,只插入/ upsert(待處理的行,然後是完成的行),讓讀者根據最新的行進行數據預測(例如)
- 1. 最終一致性和消息傳遞
- 2. 數據庫消息隊列
- 3. 消息隊列和數據庫插入
- 4. 將數據庫與消息隊列分離的最佳做法
- 5. 消息隊列與數據庫表隊列通過CRON
- 6. 尋找.NET相關的最佳實踐和庫,用於日誌記錄,數據庫池,消息隊列等
- 7. 最終與erlang一致的mnesia數據庫。最佳做法?
- 8. Hangfire與Azure SQL數據庫和MSMQ保持一些消息已排好隊列
- 9. 消息隊列'消息的數量'始終爲0
- 10. 消息隊列與消息傳遞
- 11. 分佈式數據庫 - 最終一致性含義
- 12. 同時使用消息隊列和數據庫
- 13. log4net:在數據庫的一行中記錄兩條消息?
- 14. 最終消息上的RabbitMQ RPC關閉響應隊列
- 15. Google數據存儲查詢和最終一致性
- 16. 最終一致性和更新
- 17. 最終一致性和測試用例
- 18. 順序一致性和最終一致性有什麼區別?
- 19. CQRS - 最終一致性
- 20. APNS和消息隊列
- 21. SQL Server和消息隊列
- 22. Azure隊列唯一消息
- 23. 從消息隊列中檢索數據
- 24. 是否有最小的消息隊列?
- 25. 使用數據庫表作爲消息/作業隊列的最佳方法
- 26. Rails 4 - 錯誤消息和同一頁面上的所有數據庫記錄
- 27. Apache OFBiz與Cassandra的集成和最終一致性
- 28. 將隊列的消息記錄到文本文件
- 29. 消息隊列或數據庫中插入並選擇
- 30. 最好的消息隊列中除了的RabbitMQ和SQS的消息路由
您需要的是知道什麼消息被髮送,哪些沒有被髮送 –
這可能有助於https://vimeo.com/111998645 – tomliversidge