RabbitMq消息确认模式

在mq消息传递时,为了避免消息丢失,mq引入了消息确认机制

mq是一种生产者和消费者模式,中间以mq为中介进行消息分发,将生产者与消费者隔离,生产者不必关心消息何时被消费,消费者也不关心消息如何生产,使得两者不必同步处理。 

 因此基于这种模式,可能会产生消息丢失问题,如何确保消费成功发送。以及消息成功接收,需要保证:

1、生产者的确认模式

2、消息和队列的持久化

3、消费者的确认模式

一、发布者确认模式 

        1、单个确认模式

     生产者每发送一次消息,就会等待一次消息确认,是一种同步等待的方式,效率最低

public class ConfirmServer {
    static Channel init() throws IOException, TimeoutException {
        ConnectionFactory factory = ConnectionUtil.getFactory(); //获取一个连接工厂
        Connection connection = factory.newConnection(); //创建连接
        Channel channel = connection.createChannel(); //信道
        channel.confirmSelect(); //开启确认模式
       
        return channel;
    }
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Channel channel = init();
        long l = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            channel.basicPublish("","queue",null,"hello".getBytes());
            boolean flag = channel.waitForConfirms();//等待确认
        }
        System.out.println("耗时: " + (System.currentTimeMillis() - l));

    }
}

 

         2、批量确认模式(用一个计数器,到一定数量确认一次)

public class ConfirmServer {
    static Channel init() throws IOException, TimeoutException {
        ConnectionFactory factory = ConnectionUtil.getFactory(); //获取一个连接工厂
        Connection connection = factory.newConnection(); //创建连接
        Channel channel = connection.createChannel(); //信道
        channel.confirmSelect(); //开启确认模式

        return channel;
    }
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Channel channel = init();
        long l = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 100; i++) {
            channel.basicPublish("","queue",null,"hello".getBytes());
            if(++count == 25){
                boolean flag = channel.waitForConfirms();//等待确认
                count = 0;
            }
        }
        System.out.println("耗时: " + (System.currentTimeMillis() - l));

    }
}

 但是这个方式有一个缺陷,即这一批有一个消息确认失败,mq会丢弃整批的消息,也没办法知道是哪些消息接收失败

        3、采用异步回调 

public class ConfirmServer {
    static Channel init() throws IOException, TimeoutException {
        ConnectionFactory factory = ConnectionUtil.getFactory(); //获取一个连接工厂
        Connection connection = factory.newConnection(); //创建连接
        Channel channel = connection.createChannel(); //信道
        channel.confirmSelect(); //开启确认模式
        channel.addConfirmListener((deliveryTag, multiple) -> {
            /**
             * deliveryTag 消息标识
             * multiple 为false是单个确认,为true是小于该tag的批量确认
             */
            System.out.println("接收成功回调");
            System.out.println("deliveryTag" + deliveryTag + "multiple:" + multiple);
        },(deliveryTag, multiple) -> {
            System.out.println("接收失败回调");
        });
        return channel;
    }
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        Channel channel = init();
        long l = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 100; i++) {
            channel.basicPublish("","queue",null,"hello".getBytes());

        }
        System.out.println("耗时: " + (System.currentTimeMillis() - l));

    }
}

可以看到,这是一种异步回调的方式,并且效率也是最高的,既可以单个确认,也可以批量的确认,当消息确认失败,也会调用失败的回调,返回失败的tag进行重发操作。 

二、消费者确认模式  

消费者这边分为自动和手动应答方式,自动应答在消费消息时设置true即可

public class Customer {

    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = ConnectionUtil.getFactory();
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();

       while (true){
                    //false,关闭自动应答
           channel.basicConsume("queue",false,(consumerTag, message) -> {
               System.out.println("成功接收到消息[" + consumerTag + "]:" + new String(message.getBody()));
               System.out.println(message.getEnvelope().getDeliveryTag());
               /**
                * 消息确认
                * deliveryTag 应答的标识
                * multiple  是否批量
                */
               channel.basicAck(message.getEnvelope().getDeliveryTag(),true);
               /**
                * 消息拒绝
                * deliveryTag
                * multiple 批量
                * requeue 是否重新入队,慎用(拒绝后,入队反复操作,可能导致消息积压)
                */
//               channel.basicNack(deliveryTag,multiple,requeue);
               /**
                * 消息拒绝
                * deliveryTag
                * requeue
                * 
                */
//               channel.basicReject(deliveryTag,requeue);
           },(consumerTag -> {
               System.out.println(consumerTag + "接收失败");
           }));
       }
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RabbitMQ是一种强大的开源消息队列中间件,提供了高可用、高可靠和可扩展的消息传递机制。发布确认模式RabbitMQ中的一种消息确认机制,确保消息的可靠性传递。 在发布确认模式中,生产者发送消息到交换机,然后等待RabbitMQ返回一个确认消息。只有当RabbitMQ发送了确认消息后,生产者才认为消息已经成功发送到了交换机,否则被认为发送失败。 使用发布确认模式的好处是可以确保消息不会丢失。当消息到达交换机时,RabbitMQ会立即返回一个确认消息,表示消息已经被接收并且存储到队列中。如果在发送消息的过程中出现了错误,RabbitMQ会发送一个拒绝消息,表示消息发送失败。生产者可以通过重试机制重新发送失败的消息,确保消息能够被正确处理。 在确认模式中,可以使用两种方式进行消息确认:基于事务的方式和基于确认模式的方式。基于事务的方式是将每次消息发送操作包装在事务中,如果事务提交成功,则表示消息发送成功,否则表示消息发送失败。基于确认模式的方式是设置确认模式为手动,在发送消息后,手动调用确认方法进行确认,如果确认成功则表示消息发送成功,否则表示消息发送失败。 总之,RabbitMQ的发布确认模式确保了消息的可靠传递,适用于对消息可靠性要求高的场景。使用发布确认模式可以避免消息丢失,提供了更好的消息传递保障。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值