RabbitMQ

瑞星  论坛元老 | 2025-4-14 19:18:47 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1675|帖子 1675|积分 5025

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1.谈谈你对RabbitMQ的理解?

RabbitMQ是一个生产者和消费者模型,重要负责接受、存储和转发消息。RabbitMQ重要分为生产者、消费者、Broker、Exchange和Queue。

  • 生产者就是消息的发送方,生产者将消息发送给Exchange。
  • Exchange会将消息路由到其绑定的队列Queue中,Exchange不能存储消息。
  • Queue用于存储消息,多个消费者可以订阅同一个队列,将消息发送到消费者。
  • 消费者从队列中取到消息,然后对消息进行处理。
2.交换机Exchange类型有哪些?
交换机类型重要有Fanout、Direct和Topic三种类型。

  • Fanout交换机是采取广播的形式,将消息发送给每一个绑定的Queue中。比如支付案例中,用户支付成功之后,需要通知交易服务更新订单状态,通知短信服务给用户发短信,通知积分服务给用户加积分。只需要将这些微服务的队列绑定到Fanout交换机,就可以实现发送一条消息,每个微服务都能处理自己对应的业务。
  • Direct会将吸收到的消息根据路由规则路由到指定的Queue,因此称为定向路由。Fanout交换机将消息路由给每一个与之绑定的队列,Direct交换机根据消息的RoutingKey和队列的BindingKey判断路由给哪个队列。如果多个队列具有雷同的BindingKey,则与Fanout功能类似。
  • Topic也是基于RoutingKey和BindingKey做消息路由,但是RoutingKey通常是多个单词的组合,而且以.分割。Topic交换机与队列绑定时的bindingKey可以指定通配符,#代表0个或多个词,*代表1个词。
   交换机的类型重要有三种,分别是Fanout、Direct和Topic。Fanout交换机采取广播机制,将消息发送给每个绑定的Queue。Direct是定向路由,将消息根据RoutingKey和BindingKey路由到指定的Queue中。Topic也是基于RoutingKey和BindingKey做消息队列,但是RoutingKey通常是多个单词的组合,并以’.'分割。
  3.如何声明队列和交换机?
Spring提供了基于@RabbitListener注解方式来声明队列、交换机和BindingKey。@RabbitListrner注解的bindings属性,类型为@QueueBinding注解,在这个注解里面传入三个属性:value、exchange和key。

  • value指定队列名
  • exchange指定交换机名和类型
  • key指定对应的BindingKey,可以使用数组指定多个。
   RabbitMQ声明队列、交换机和BindingKey需要使用到@RabbitListener注解的binding属性,在这个属性中分别指定队列名、交换机名和BindingKey。
  4.RabbitMQ如何实现消息的发送?
发消息用的是rabbitTemplate停止中的convertAndSend方法,方法中第一个参数的为交换机名称,第二个参数为routingKey,第三个是发送的消息。消息在网络中传输是基于JDK序列化的,JDK序列化存在以下问题:

  • JDK序列化存在安全风险,在反序列化的时间容易被代码侵入。
  • JDK序列化占用空间太多
  • JDK序列化可读性很差
JDK序列化方式并不符合。我们希望消息体的体积更小、可读性更高,因此可以使用JSON方式来做序列化和反序列化。
   RabbitMQ通过convertAndSend方法来发送消息,第一个参数为交换机名,第二个参数为routingKey,第三个参数为发送的消息。
  5.RabbitMQ如何包管消息的可靠性?
可能出现消息丢失的场景分别是生产者发送消息时消息丢失、MQ宕机导致消息丢失,消费者处理消息时抛非常导致消息丢失。
为了包管生产者的可靠性,可以采取发送者重试机制和发送者确认机制。

  • 发送者重试机制,在配置文件中的spring rabbitmq-template-retry下开启重试机制,并设置失败后的等候时间以及最大重试次数。如果对业务性能有要求,发起禁用重试机制。
  • 发送者确认机制,有两种机制包括confirm和return。

    • 当消息投递到MQ,但是路由失败时,通过Return返回非常信息,同时通过confirm返回ACK简直认信息,代表投递成功。
    • 消息投递成功,通过confirm返回ACK。
    • 消息投递失败,返回NACK。

为了包管MQ的可靠性,可以采取数据持久化。

  • 交换机持久化,在控制台的Exchanges页面将Durability参数设置为Durable开启持久化。
  • 队列持久化,在控制台的Queue页面将Durability参数设置为Durable开启持久化。
  • 消息持久化,在发送消息的时间,配置持久化属性。
为了包管消费者的可靠性采取消费者确认机制、失败重试机制以及失败处理策略。

  • 消费者确认机制,当消费者处理消息竣事后,应该向RabbitMQ发送一个回执,告知RabbitMQ自己消息处理状态。ack:成功处理消息,RabbitMQ从队列中删除该消息。nack:消息处理失败,RabbitMQ需要再次投递消息给消费者。reject:消息处理失败并拒绝该消息,比如消息在转换过程中出现非常,RabbitMQ会从队列中删除该消息。
  • 失败者重试机制,当消费者出现非常后,消息会不停requeue(重入队)到队列,再重新发送给消费者。如果消费者再次执行依然出错,消息会再次requeue到队列,再次投递,直到消息处理成功为止。开启本地重试时,消息处理过程中抛出非常,不会requeue到队列,而是在消费者本地重试。重试达到最大次数后,Spring会返回reject,消息会被丢弃。
  • 失败处理策略,Spring允许我们自定义重试次数耗尽后的消息处理策略,这个策略是由MessageRecovery接口来定义的。失败后将消息投递到一个指定的,专门存放非常消息的队列,后续由人工会合处理。
   RabbitMQ为了包管生产者的可靠性,通过重试机制和确认机制实现。重试机制需要设置发送失败后的等候时间以及最大重连次数。确认机制是消息投递成功返回ACK,消息投递失败返回NACK。
RabbitMQ为了包管MQ的可靠性,采取数据持久化,包括交换机持久化、队列持久化和消息持久化,都是需要配置Durability属性来开启持久化的。
RabbitMQ为了包管消费者的可靠性,采取消费者重试机制、确认机制以及失败处理策略。消费者重试机制是当消费者出现非常后,消息不停requeue到队列,再重发给消费者。确认机制是在处理消息后,向RabbtiMQ发送处理状态。ack表现消息处理成功,直接从队列中删除消息。nack表现消息处理失败,需要RabbitMQ再次投递给消费者。失败处理逻辑就是,消息处理失败后会投递到一个指定的队列中,等候后续人工处理。
  6.业务幂等性的常见方案有哪些?
采取确认机制和重试机制中,很有可能出现同一个消息被重复消费的可能,可以采取唯一ID的方式来包管幂等性。

  • 每一条消息都生成一个唯一ID,与消息一起投递给消费者。
  • 消费者吸收到消息后处理自己的业务,业务处理成功后将消息ID生存到数据库。
  • 如果下次又收到雷同消息,去数据库查询判断是否存在,存在则为重复消息放弃处理。
   采取唯一ID的方式确保业务幂等性,每条消息都生成一个唯一ID,消费者处理完消息后将消息ID存放到数据库。下次收到雷同的消息就去数据库中查询,如果存在就是重复消息。
  7.如何解决消息积存?
消息堆积的缘故原由就是生产者生成速度大于消费者消费速度。
解决消息堆积重要有三种方法:

  • 单台实例启动多线程,加速消息消费
  • 开启工作队列模型,多个实例订阅同一个queue,分摊使命。
  • 使用惰性队列,队列吸收到的消息直接存入磁盘,需要的时间再从磁盘中拿出,推送给消费者。
8.如何确保支付服务与交易服务之间的订单状态一致性?

  • 首先,支付服务会在用户支付成功以后使用MQ消息通知交易服务,完成订单状态同步。
  • 为了包管MQ消息的可靠性,我们采取了生产者确认机制、消费者确认、消费者失败重试等策略,确保消息投递和处理的可靠性。同时也开启了MQ的持久化,制止因服务故障导致消息丢失。因此无论是发送方、MQ自己和消费者都能确保消息可靠。这就可以确保消息肯定投递到消费者,至少让消费者处理一次。
  • 由于可能会出现重复投递消息,最后,我们还在交易服务更新订单状态时做了业务幂等判断,制止因消息重复消费导致订单状态非常。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

瑞星

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表