如果发布者在收到确认之前终止会怎么样?

时间:2016-03-01 12:58:24

标签: rabbitmq message-queue durability

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

  

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

     

例如,请考虑以下情况:

     
      
  • 客户端将持久性消息发布到持久队列
  •   
  • 客户端使用队列中的消息(注意消息是持久的并且队列持久),但还没有确认,
  •   
  • 经纪人死亡并重新启动,
  •   
  • 客户端重新连接并开始使用消息。
  •   
     

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

但是,如果使用确认,发布服务器在收到确认之前停止运行,并且由于某种原因(即网络故障)消息未传送到队列。

假设我们有一个简单的REST端点,我们可以在其中发布新的COMMENTS,并且在创建新的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 个答案:

答案 0 :(得分:1)

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