Java面试题-Rabbitmq

Rabbitmq的6种收发模式是什么

  • 简单模式:一个队列中一条消息,只能被被一个消费者使用
  • 工作模式:一个生产者,多个消费者,每个消费者获取的消息唯一
  • 发布和订阅模式:一个生产者的信息被多个消费者消费
  • 主题模式:生产者,一个交换机,模糊路由匹配原则,多个队列,多个消费者
  • 路由模式:生产者发送的消息根据定义的路由规则决定往哪个队列发送消息
  • RPC异步调用模式:客户端Client发送消息到消息队列,服务器端Server获取消息,再发送给另一个消息队列,向客户端Client返回消息处理结果

Rabbitmq如何防止消息丢失

  • RabbitMQ消息丢失的三种情况
    在这里插入图片描述
    第一种:生产者弄丢了数据。生产者将数据发送到 RabbitMQ 的时候,可能数据就在半路给搞丢了,因为网络问题啥的,都有可能。
    第二种:RabbitMQ 弄丢了数据。MQ还没有持久化自己挂了
    第三种:消费端弄丢了数据。刚消费到,还没处理,结果进程挂了,比如重启了。

  • RabbitMQ消息丢失解决方案
    在这里插入图片描述

  • 针对生产者

    • 方案1:用 RabbitMQ 提供的事务功能,就是生产者发送数据之前开启 RabbitMQ 事务,如果消息发送没有成功被 RabbitMQ 接收到,那 么生产者会收到异常报错,此时就可以回滚事务,然后重试发送消息;如果收到了消息,那么可以提交事务。
    • 方案2:生产者完成消息发送后,可能因为网络或Rabbitmq自身原因,消息没有被Rabbitmq正确接收,采用消息确认发送模式,即Confirm模式,向Rabbitmq发送详细后,等待服务器返回确认消息
      1. 开启Confirm模式:连接服务器后调用channel.confirmSelect(),每次写的消息都会分配一个唯一的id,然后写入Rabbitmq之中
      2. 接收Rabbitmq返回确认信息:Rabbitmq会给你返回一个ack消息,告诉你这个消息发送OK了,如果回调一个nack接口,则这个消息接 收失败,生产者可以重新发送
      • 可以结合这个机制自己在内存里维护每个消息 id 的状态,如果超过一定时间还没接收到这个消息的回调,就可以重发
  • 针对Rabbitmq

    • Rabbitmq消息奥村在内存中,服务器重启或崩溃,内存数据会丢失
    • 方案:持久化
      1. 队列持久化:创建队列时,持久化参数设置为true 在这里插入图片描述
      2. 消息持久化:发送消息时,消息添加添加持久化属性,参数:MessageProperties.PERSISTENT_TEXT_PLAIN,就是将消息设置为持久化 在这里插入图片描述
  • 针对消费者

    • 方案:手动确认模式:关闭 RabbitMQ 的自动 ack,采用手动ack (消息应答机制),每次在确保处理完这个消息之后,在代码里手动调用ack。这样就可以避免消息还没有处理完就ack。才把消息从内存删除。

如何控制消息重复消费问题

  • 正常情况下,消费者消费信息完毕后,Rabbitmq会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除,但是由于网络波动等原因,可能造成消费者向Rabbitmq返回的确认信息丢失。Rabbitmq长时间收不到确认信息,于是会向消费者再次推送该条message,这样就造成了重复消费。

  • 解决方案:

    • 将消费者的业务逻辑接口设计成幂等性,比如生成订单的时候带上唯一的订单编号,将订单编号保存到redis中,判断下redis中是否存在订单编号,如果存在则该消息已消费,如果不存在,则该消息为消费
    • 将已消费的信息id存入redis,处理消息前,先判断redis中是否已存在该信息的id
    • 操作数据前,先从数据库查询,判断数据是否已存在或修改
    • 添加数据时,数据库中设置唯一的id,防止重复添加数据
  • 注意:如果是高并发时,可以将消费者的业务逻辑接口设计成幂等性,将信息的id(或者是具有唯一标志性的字段值如订单编号)加上分布式锁,防止被多个服务器的消费者抢到该信息,然后将信息的id(或者是具有唯一标志性的字段值如订单编号)存入redis中,根据信息的id(或者是具有唯一标志性的字段值如订单编号)存在与否,判断该消息是否已被消费,是否对数据进行操作

消费者无法处理消息怎么办

  • 使用死信队列
    • 死信队列
      消费者入如果无法处理消息或处理失败,可以选择将消息发送到死信队列,之后再采用其他方式来处理死信队列中的信息
    • 为什么使用死信队列
      消费者由于某种原因消息处理失败,并希望这条信息可以被其他方式再次被处理,这时就可以将信息发送到死信队列,让其他消费者来处理

订单系统中,如何取消未付款的订单来释放库存

  • 使用延迟消息(延迟队列)
    • 订单系统中,用户下单后,项Rabbitmq发送一个延迟信息,例如设置时间延迟30分钟
    • 30分钟后消息投递到消费者,消费者检查订单的付款状态,取消未支付的订单

如何保证消息的处理顺序

  • 生产者将所有需要顺序处理的消息发送到同一个队列
  • 只用一个消费者从队列接收消息

发生消息堆积怎么办

  • 临时增加消费者数量,加快消费速度
  • 将堆积消息丢弃,系统空闲时间再重新发送这些消息
  • 启动一个消费者接收所有堆积的消息,并将消息直接发送到其他队列,使当前队列后续其他消息可以时时被消费
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值