【问题标题】:What happens if a Publisher terminates before receive ack?如果发布者在收到确认之前终止会发生什么?
【发布时间】:2016-03-01 21:47:05
【问题描述】:

我想确保某些类型的消息不会丢失,因此我应该使用Confirms (aka Publisher Acknowledgements)

如果代理在说之前崩溃,它会丢失持久消息 消息被写入磁盘。在某些情况下,这会导致 经纪人以令人惊讶的方式行事。

例如,考虑这种情况:

  • 客户端将持久消息发布到持久队列
  • 客户端使用队列中的消息(注意消息是持久的并且队列是持久的),但尚未确认它,
  • 代理终止并重新启动,并且
  • 客户端重新连接并开始使用消息。

此时,客户端可以合理地假设消息 将再次交付。情况并非如此:重新启动已导致 经纪人丢失消息。为了保证持久性,一个 客户应该使用确认。

但是,如果使用确认,Publisher 在收到 ack 之前就宕机了,并且由于某种原因(即网络故障)消息没有传递到队列中。

假设我们有一个简单的 REST 端点,我们可以在其中发布新的评论,并且当创建新的评论时,我们希望在队列中发布一条消息。 (注意:如果我发送一条新 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()
  }

}

当服务器重新启动时,通道消失了,消息永远无法传递。 我想到的一种解决方案是,在重新启动后,查询存储库中最近的 cmets(¿类似于崩溃前最后 3 分钟之间创建的 cmets?),并为每个消息发送一条消息并等待确认。

【问题讨论】:

    标签: rabbitmq message-queue durability


    【解决方案1】:

    您担心的不再是 RabbitMQ 唯一的问题,而是distributed transaction 的问题。这个discussion 提供了一种合理的轻量级解决方案。并且有更严格的解决方案,例如两阶段提交、三阶段提交等,以确保在真正需要时数据一致。

    【讨论】:

      猜你喜欢
      • 2012-06-30
      • 2021-10-04
      • 2014-04-04
      • 2013-02-21
      • 1970-01-01
      • 1970-01-01
      • 2015-11-25
      • 1970-01-01
      • 2010-10-07
      相关资源
      最近更新 更多