RabbitMQ 消息模式与问题记录

RabbitMQ 问题记录

  1. RabbitMQ提供了6种消息模型,但是第6种其实是RPC,并不是MQ。
    第6种其实是RPC,并不是MQ
    1.消费者如果正在处理消息的时候突然宕机怎么办?
    答:自动确认改变为手动确认ACK
    2.当生产者持续发送消息,而消费者处理不过来时该怎么办?
    答:使用work 模型:让多个消费者绑定到一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。
    3.如果rabbitMq挂了,消息怎么办?
    答:持久化:队列,交换机。对消息进行MessageProperties.Persistent(持久化)
    4.生产者发消息,但是没有发成功?
    答:rabbitMq发消息告诉生产者已经接受到消息(消息重试)

以上四点用来解决消息丢失的问题。

消费者的消息确认机制(Acknowlage)

消息一旦被消费者接收,队列中的消息就会被删除。
那么问题来了:RabbitMQ怎么知道消息被接收了呢?

这就要通过消息确认机制(Acknowlege)来实现了。当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收。不过这种回执ACK分两种情况:
- 自动ACK:消息一旦被接收,消费者自动发送ACK
- 手动ACK:消息接收后,不会发送ACK,需要手动调用

如何设置,则需要看消息的重要性:
- 如果消息不太重要,丢失也没有影响,那么自动ACK会比较方便
- 如果消息非常重要,不容丢失。那么最好在消费完成后手动ACK,否则接收消息后就自动ACK,RabbitMQ就会把消息从队列中删除。如果此时消费者宕机,那么消息就丢失了。

如果要手动ACK,需要改动我们的代码:

		// 定义队列的消费者
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            // 获取消息,并且处理,这个方法类似事件监听,如果有消息的时候,会被自动调用
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, BasicProperties properties,
                    byte[] body) throws IOException {
                // body 即消息体
                String msg = new String(body);

                // 手动进行ACK
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        };
        // 监听队列,第二个参数false,手动进行ACK
        channel.basicConsume(QUEUE_NAME, false, consumer);

消息堆积的处理

启动多个消费者,让多个消费者绑定到同一个队列,共同消费该队列中的消息。
然而现实中,可能不同消费者处理消息的耗时时间不同。所以可以修改设置,让消费者同一时间只接收一条消息,这样处理完成之前,就不会接收更多消息,就可以让处理快的人,接收更多消息 :

 		// 声明队列
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        
        // 设置每个消费者同时只能处理一条消息
        channel.basicQos(1);
        
        // 定义队列的消费者
        DefaultConsumer consumer = new DefaultConsumer(channel) {

持久化 队列,交换机,消息

如何避免消息丢失?
1) 消费者的ACK机制。可以防止消费者丢失消息。
2) 但是,如果在消费者消费之前,MQ就宕机了,消息就没了。

要将消息持久化,前提是:队列、Exchange都持久化

一、交换机持久化
在这里插入图片描述
二、队列持久化
在这里插入图片描述
三、消息持久化
在这里插入图片描述
PERSISTENT_TEXT_PLAIN对应的deliveryMode 2
在这里插入图片描述

生产者消息丢失

 		// 获取通道
        Channel channel = connection.createChannel();

        //生产者消息确认
        channel.confirmSelect();
        ....
		//等待消息确认(失败抛出异常)
        channel.waitForConfirmsOrDie();
        channel.close();

但是该情况会出现消息重复发送(因网络或者其他问题导致),所以需要对业务进行幂等性(同一接口被重复执行,其结果一致)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值