原文链接:https://blog.csdn.net/qq_29569183/article/details/111634015

    使用MQ中间件时,保证消息准确发送和消费以及幂等性等问题是我们都需要考虑的。解决这些问题需要先来理解三个概念。

    在RabbitMQ的确认有两种,其中一个consumer acknowledgement简称为ACK,另一个叫publisher confirm这里我们简称为confirm。

    ACK (consumer acknowledgemenet)
    基于AMQP协议,定义个消费者consumer到RabbitMQ broker的确认,表示一条消息已经被客户端正确处理。根据AMQP协议规定,consumer acknowledgemenet是通过basic.ack方法实现的,consumer在收到一条消息后,可以向broker发送basic.ack方法,确认一条消息已经收到。在默认的情况下,consumer acknowledgement模式是开启的,如果不想发送basic.ack,可以在发送basic.consume方法时指定no-ack参数,关闭consumer acknowledgement模式。

    所以在开发中我们可以基于ACK的机制通过手动ACK的方式来实现消息的准确消费

    confirm (Publisher confirm)
    RabbitMQ扩展AMQP协议定义了从broker到生产者publisher的”确认”,将其称之为confirm。Publisher confirm并没有在AMQ协议的基础上添加新的确认方法,而是复用了basic.ack方法。需要注意的是publisher confirm模式并不是默认打开的,需要调用confirm.select方法将channel设置成confirm模式。当开启了confirm模式之后,只有当一条消息被broker接受之后,publisher才会收到这条消息的confirm,也就是一个basic.ack方法。

    在开发中我们可以通过confirm方式实现消息发送的确认,在考虑性能的情况下可以使用这种方式代替事务方式保证消息发送成功。

    事务(transaction)
    RabbitMQ支持事务(transaction)。事务模式也不是默认开启的,需要调用tx.select方法开启事务模式。当开启了事务模式后,只有当一个事务被所有的broker接受之后,tx.commit-ok才会返回给客户端。
    confirm模式和开启事务模式都可以保证消息被所有的broker接受,所以在发送消息场景中,使用事务或使用confirm都有可以达到消息准确发送的目的。

    当然,开启confirm模式和开启事务模式还是有一些区别的。confirm是针对一条消息的,而事务是可以针对多条消息的(当然是针对同一个queue的多条消息)。
    另外就是,confirm模式只是针对publisher的设置,而事务模式即可以针对publisher,也可以针对consumer。
    如果针对publisher设置事务模式,则我们可以将多个basic.publish方法放在一个事务中,当所有的publish的消息被所有的broker接受后,publisher client会收到tx.commit-ok的方法。如果针对consumer设置事务模式,则我们可以将多个basic.ack方法放在一个事务中,收到tx.commit-ok时表示这些消息都被确认了。

    [

    ](https://blog.csdn.net/qq_29569183/article/details/111634015)