RabbitMQ篇

大家好我是小明,今天学习消息中间件RabbitMQ


`

文章目录

  • [1. RabbbitMQ如何保证消息不丢失问题(最高频)](#1. RabbbitMQ如何保证消息不丢失问题(最高频))
  • [2. RabbitMQ消息的重复消费如何解决??](#2. RabbitMQ消息的重复消费如何解决??)
  • [3. RabbitMQ中的死信交换机(RabbitMQ延迟队列有了解过吗?)](#3. RabbitMQ中的死信交换机(RabbitMQ延迟队列有了解过吗?))
  • [4. RabbitMQ如果有100万条消息堆积在MQ,如何解决(信息堆积怎么解决)](#4. RabbitMQ如果有100万条消息堆积在MQ,如何解决(信息堆积怎么解决))
  • [5. RabbitMQ的高可用机制有哪些有了解过吗。](#5. RabbitMQ的高可用机制有哪些有了解过吗。)

复习大纲


1. RabbbitMQ如何保证消息不丢失问题(最高频)

这个这么回答:

生产者确认机制: 消息发到MQ后会返回一个ack给生产者,表示消息成功发送到mq.
消费者确认机制: 消费者处理完消息后发送ack给MQ,MQ收到ack回执后,MQ才会删除该消息。

SpringAMQP则允许配置三种消费者消息确认确认模式:

  1. 自动确认: RabbitMQ 会⾃动把发送出去的消息置为确认, 然后从内存(或者磁盘)中删除, ⽽不管消费者是否真正地消费到了这些消息.
  2. 手动确认: 费者处理完业务后,手动调用 channel.basicAck() 确认;处理失败则调用 basicNack()/basicReject() 拒绝(可重入队列或丢弃)。
  3. 批量确认(批量手动) : 就是消费者处理完一批消息之后就确认这一批消息,下面看批量确认代码
java 复制代码
// 批量确认示例(假设累计处理100条后确认)
private int batchCount = 0;
private long lastDeliveryTag = 0;

@RabbitListener(queues = "batch.queue")
public void onBatchMessage(Message message, Channel channel) throws IOException {
    long deliveryTag = message.getMessageProperties().getDeliveryTag();
    try {
        // 处理业务逻辑
        processMessage(message);
        batchCount++;
        lastDeliveryTag = deliveryTag;
        // 累计100条批量确认
        if (batchCount >= 100) {
            channel.basicAck(lastDeliveryTag, true); // 确认所有<=lastDeliveryTag的消息
            batchCount = 0; // 重置计数器
        }
    } catch (Exception e) {
        // 批量处理失败,拒绝当前消息并停止批量
        channel.basicNack(deliveryTag, false, true);
        batchCount = 0;
    }
}

假如说:消费者消息确认失败怎么办

可以利用Spring的retry机制,在消费者出现异常时利用本地重试机制,设置重试次数,当到达一定次数还是失败,就把消息丢到死信队列,由人工处理。

消息持久化: MQ默认是内存存储消息,开启持久化可以保证消息在MQ中消息不丢失。

面试回答:


2. RabbitMQ消息的重复消费如何解决??

问题:

消费者处理完消息之后,发送的ack用于网络波动没有接收到,mq再次发送该消息给消费者处理,导致消费者重复消费。

解决: 消息带身份标识(id,支付id,订单id),消费者校验该id是否存在进行处理,如果存在直接跳过处理流程。


3. RabbitMQ中的死信交换机(RabbitMQ延迟队列有了解过吗?)

死信出现的三种情况?

  1. 消息被拒绝(Rejected):消费者调用了 basicReject 或 basicNack 方法并且方法的第二个参数 requeue(重入队列)被设置为 false,
  2. 消息过期(TTL Expired):队列设置了过期时间: 整个队列里的所有消息都有统一的过期时间(x-message-ttl)。消息本身设置了过期时间: 发送消息时给这条消息单独设置了过期时间(expiration 属性)。
  3. 队列达到最大长度:队列像一个桶,桶满了,再往里面倒水,水就会溢出来。溢出的消息就会变成死信。

延迟队列: 进入队列的消息会被延迟消费的队列

使用场景:

  • 30 分钟内支付订单
  • 定时发布作品
  • 限时优惠
    延迟队列的实现原理(TTL + 死信队列)
  1. 创建一个 "延迟队列"(实际是普通队列),不给它配置消费者(消息不会被立即消费);
  2. 给这个延迟队列设置 TTL(消息过期时间),并绑定死信交换机;
  3. 消息发送到这个延迟队列后,会在队列里 "等待" 直到过期;
  4. 消息过期后,会自动变成死信,被转发到绑定的死信交换机;
  5. 死信交换机再把消息路由到实际消费队列,消费者监听这个队列,就能拿到 "延迟后的消息"。

简单来说:延迟队列的本质是 "让消息先在一个'临时队列'里等过期,过期后自动转到消费队列被处理",TTL + 死信是实现这个逻辑的 "巧劲"。


4. RabbitMQ如果有100万条消息堆积在MQ,如何解决(信息堆积怎么解决)

当生产者发送消息的速度超过了消费者处理消息的速度,就会导致队列中的消息堆积,直到队列存储消息达到上限。之后发送的消息就会成为死信,可能会被丢弃,这就是消息堆积问题。

解决消息堆积三种思路:

  • 增加更多消费者,提高消费速度
  • 在消费者内开启线程池加快消息的消息的处理速度
  • 扩大队列容积,提高堆积上线

这么扩大队列消息容积呢??

惰性队列

设置队列属性为lazy该队列就会变成惰性队列。

  • 消息存储在硬盘中而非内存。
  • 消费者需要消费消息时才会从磁盘中读取并加载。
  • 支持数百万消息存储。

这样就扩大消息的存储了。


5. RabbitMQ的高可用机制有哪些有了解过吗。

镜像集群

本质: 主从模式

具备以下特征:

  • 交换机,队列,队列中的消息在各个MQ节点的镜像节点进行同步。

  • 创建队列的节点被称为队列主节点,备份到的节点叫做队列的进镜像点。

  • 一个队列的主节点可能是另一个队列的镜像节点。

  • 所有操作都是由主节点完成,然后同步镜像节点。

  • 主节点宕机后,镜像节点会代替成新主节点,主节点在数据同步时宕机的会造成数据丢失

    仲裁队列

  • 和镜像队列一样,都是主从模式,支持主从数据同步

  • 使用非常简单,没有复杂的配置

  • **主从同步使用Raft协议,强一致性


好了今天就到这里

相关推荐
Trouvaille ~8 小时前
【Redis篇】初识 Redis:特性、应用场景与版本演进
数据结构·数据库·redis·分布式·缓存·中间件·持久化
米高梅狮子10 小时前
Ceph 分布式存储 部署
linux·运维·数据库·分布式·ceph·docker·华为云
郭龙_Jack10 小时前
跨境电商 平台 - ERP - 内部子系统 交互方式总图
分布式·教育电商
喝醉酒的小白10 小时前
Kafka 集群应急故障排查手册
分布式·kafka
无籽西瓜a10 小时前
【西瓜带你学Kafka | 第八期】 Kafka的主从同步、消息可靠性、流处理与顺序消费(文含图解)
java·分布式·后端·kafka·消息队列·mq
qqVHU10 小时前
kafka笔记
笔记·分布式·kafka
醉颜凉10 小时前
Kafka 消息过期时间设置与清理机制全解析
分布式·kafka·linq
Jinkxs10 小时前
SkyWalking - Kafka _ RabbitMQ 消息链路追踪支持
kafka·rabbitmq·skywalking
犬小哈10 小时前
滴滴二面:你项目为什么选择 RocketMQ,而不是 Kafka? 我:支支吾吾....
分布式·kafka·rocketmq
Jinkxs10 小时前
Kafka - 日志刷盘策略优化:sync.ms、flush.messages配置
分布式·kafka