说明:在rabbitMQ中,我们为了解决服务器异常导致数据丢失的问题,我们可以采用rabbitMQ的持久化机制,但是我们如何确定生产者将消息发送给了rabbitMQ呢,那么我们采用两种协议的模式。
(1)、AMQP实现了事务机制
(2)、confirm模式
一、事务机制
txSelect:用户将当前channel设置为transation模式
txCommit:用于提交事务
txRollback:用于回滚事务
二、实例
(1)生产者:
import java.io.IOException; import java.util.concurrent.TimeoutException; import com.demo.rabbitMQ.util.ConnectionUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; public class TransationProduce { private static final String QUEUE_NAME="test_queue_transation"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection=null; Channel channel=null; try { //获取连接 connection = ConnectionUtils.getConnection(); //创建通道 channel = connection.createChannel(); //声明队列 channel.queueDeclare(QUEUE_NAME, false, false, false, null); String msg="hello tx"; //开启事务模式 channel.txSelect(); //发布消息 channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); //提交事务 channel.txCommit(); } catch (Exception e) { channel.txRollback(); System.out.println("send message rollback"); }finally { channel.close(); connection.close(); } } } |
(2) 消费者
import java.io.IOException; import java.util.concurrent.TimeoutException; import com.demo.rabbitMQ.util.ConnectionUtils; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.DefaultConsumer; import com.rabbitmq.client.Envelope; import com.rabbitmq.client.AMQP.BasicProperties; public class Consumer { private static final String QUEUE_NAME="test_queue_transation"; public static void main(String[] args) throws IOException, TimeoutException { //获取连接 Connection connection = ConnectionUtils.getConnection(); //获取通道 Channel channel = connection.createChannel(); //消息持久化 boolean durable=false; //声明队列 channel.queueDeclare(QUEUE_NAME, durable, false, false, null); //保证一次只分发一个 channel.basicQos(1); //定义一个消费者 DefaultConsumer defaultConsumer = new DefaultConsumer(channel) { //一旦有消息就会触发该方法 @Override public void handleDelivery(String consumerTag,Envelope envelope,BasicProperties basicProperties,byte[] body) throws IOException { String msg=new String(body,"utf-8"); System.out.println("===========:"+msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }finally { System.out.println("=================consumer1 over================"); //手动应答 channel.basicAck(envelope.getDeliveryTag(), false); } } }; //关闭自动应答 boolean autoAck=false; //监听队列 channel.basicConsume(QUEUE_NAME, autoAck, defaultConsumer); } } |
注意:这种模式走的通信太多,大量请求发往rabbitMQ,降低rabbitMQ的吞吐量。
源码地址:https://github.com/Carlutf8/rabbitMQ