【问题标题】:Mysql transactions and RabbitMqMysql 事务和 RabbitMq
【发布时间】:2015-04-12 09:18:08
【问题描述】:

我必须在 mysql 数据库中保存,然后通过 rabbitmq 向我的客户发送一个事件。

现在当推送到 RMq 时,如果由于某种原因失败,我需要回滚保存。应该是全有或全无,数据库中不能有未发生事件的数据。

本质上,

Begin Transaction
Save to db
Push to queue
If exception rollback else commit
End transaction

另一种方法

现在我只能在事务中进行保存操作。然后,如果失败,可以通过某种方式重试排队,但这会变得过于复杂。

在这方面有什么最佳做法吗?关于遵循哪种方法的任何建议。

PS:rmq 上的事件包含一些数据已更改的 id。客户端应为更改的 ID 执行 http get 以执行其操作。

【问题讨论】:

    标签: java mysql sql database rabbitmq


    【解决方案1】:

    在这种异构环境中,您可以使用Two Phase Commits。您将“脏”记录添加到数据库,发布消息,然后编辑记录以将其标记为“干净”并准备就绪。

    此外,当您处理消息中间件时,您必须准备好一些消息可能会丢失或它们的消费者无法完全处理它,因此可能需要来自消费者的一些反馈,例如您发布消息以及消费者何时收到它,然后它将记录添加到数据库。

    【讨论】:

      【解决方案2】:

      如果我理解正确,您主要关心的是您是否发布了消息以成功交换。您可以在 RabbitMQ 中使用Confirms 来确保您的消息被队列接受。

      根据您在数据库中设计更新的方式以及从数据库更新到您的客户获得 ID 所容忍的时间差异,您会想到以下几点:

      1. 您可以在数据库中添加一个新字段,您可以将其用作标志来检查是否将特定更新的消息发送到 RabbitMQ。当您进行更新时,您将标志设置为 0,尝试将消息发布到交易所,如果成功,您将标志更新为 1。如果您需要使用旧值直到向客户端发送消息,这可能会很复杂已发送,将要求您每隔一段时间浏览数据库,并尝试为所有未将标志设置为 1 的行再次向 RabbitMQ 发送消息。

      2. 将消息发布到 RabbitMQ,如果得到确认,则提交数据库更新。如果由于任何原因提交失败,您的客户端将进行更新,但会获取通常不会有问题的旧值,但这实际上取决于您的应用程序。这可能是更好/更简单的方法,尤其是因为没有理由期望任何事情都会不断失败。您还应该考虑在客户端从收到更新的 ID 到实际执行更新(为数据库更新留出一些时间)的时间添加某种短暂的延迟。

      【讨论】:

        【解决方案3】:

        嗯,你几乎做对了所有事情。 RabbitMQ 大佬发表了一篇关于信号量队列的好文章:https://www.rabbitmq.com/blog/2014/02/19/distributed-semaphores-with-rabbitmq/

        我认为这是“最佳实践”,因为它是由参与开发 RabbitMQ 的人编写的。

        【讨论】:

        • 感谢回复,但我不明白这是如何解决原子性问题的,请您详细说明
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-06-30
        • 2012-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多