自学内容网 自学内容网

消息队列面试题——第三篇

1. RabbitMQ的事务机制

RabbitMQ支持的事务,是保证消息发送的原子性。

它允许发布者在一个事务内发布多条消息,并通过提交和回滚确保所有消息的原子性操作,这表示要么所有消息都成功发布,要么没有消息被发布。

使用方式和数据库的事务方式很像

  • 开始事务
  • 发布消息
  • 提交事务(如果成功)回滚事务(如果失败)
    在这里插入图片描述
    需要注意,事务消息的性能比较差,因为一开始事务需要请求broker并等待broker的响应,确认没问题后,再发送消息,且后续的提交事务也需要等待broker的确认。这个操作是同步的所以性能比较低。

一般采用confirm模式替代,有批量confirm模式和异步confirm模式。

2. RabbitMQ的routing key和binding key的最大长度是多少字节

RabbitMQ的routing key和binding key的最大长度是255字节,超过这个长度的键会被RabbitMQ拒绝。

  • Routing Key:生产者发送消息时附带的一个键,用于交换机根据该键将消息路由到相应的队列
  • binding key:在队列和交换机绑定时指定的键,用于定义交换机如何根据路由键将消息路由到队列。

3. RabbitMQ如何保证消息的顺序性

RabbitMQ如果要保证消息的顺序性,首先生产者需要 1.按序发送,确认上一条消息发送成功后再发送下一条。然后 2.需要使得这类消息仅发送至一个队列,且 3. 只有一个消费者消费这个队列4. 消费者必须消费完这条消息后,在消费另一条消息,不能是多线程并发消费,这样才能保证消息的顺序性。

如果要全局消息顺序,那么全局就只使用一个队列。

4. RabbitMQ的工作模式

RabbitMQ实际上可以分为七种模式

  1. 简单模式
    作用:生产者将消息发送到队列,消费者从队列中获取消息,每条消息只能被一个消费者消费。

  2. 工作队列模式
    作用:通过多个消费者分担任务,达到负载均衡的目的。消息在多个消费者之间分配,每条消息只能被一个消费者处理。
    在这里插入图片描述

  3. 发布/订阅模式
    作用:消息发布到交换机,所有绑定到交换机的队列都会收到消息,常用的交换机类型是fanout。
    适用场景:适用于广播消息的场景,如日志处理、事件通知等
    在这里插入图片描述

  4. 路由模式
    作用:消息发布到交换机,并根据路由键将消息发送到相应的队列,常用的交换机类型是direct。
    在这里插入图片描述

  5. 主题模式
    作用:消息发布到交换机,并根据路由键模式(通配符匹配)将消息发送到相应的队列,常用的交换机类型是topic。
    在这里插入图片描述

  6. RPC模式
    作用:实现远程调用,客户端发送请求消息到队列,服务器端处理后返回响应消息。

  7. 发布确认模式
    作用:用于确保消息已经成功发布并被broker接收。

5. RabbitMQ的缺点

  1. 性能问题
  • 当队列中堆积了大量消息时,RabbitMQ的性能会急剧下降。因为他需要处理和存储这些消息,尤其是在内存和磁盘资源有限的情况下,性能影响更为明显。
  • 相比kafka和rocketMQ,他的性能通常是最差的。
  1. 开发语言限制
    RabbitMQ用Erlang语言开发

  2. 功能性不足
    相比Kafka和RocketMQ,RabbitMQ在一些高级功能上可能不如他们丰富。

6. RabbitMQ中,如何保证消息的持久化

RabbitMQ的持久化分为 队列/交换机的持久化消息的持久化 两种。

  1. 将队列和交换机的 Durable 设置为True。这样创建的队列和交换机都是持久化的,即RabbitMQ服务器重启后,队列和交换机的元数据会被保留。
  2. 消息的持久化是在生产者发送消息时,将Delivery mode设置为2,表示会持久化消息,这样的消息在发送到持久化队列后,服务器重启后消息也还存在着。

Delivery Mode扩展

  • 默认为1,表示非持久化消息,当消息发送至broker,不会将其写入磁盘,如果消费者还未消费到这条消息,broker宕机了,那么消息就丢失了。
  • 参数设置为2,表示持久化消息,会写入到磁盘,但是这个过程实际上是异步的,所以正常情况下即使broker宕机了,也有可能丢消息,只是能保证大部分消息的持久化。

7. RabbitMQ中的Channel是什么

RabbitMQ在网络层有Connection 和 Channel两个概念。

Connection其实对应的就是一条TCP连接,而Channel是Connection中的虚拟连接,一个Connection可以创建多个虚拟连接。

在RabbitMQ中,客户端和Broker之间的通信是基于Channel的,这样可以减少实际的TCP连接数,节省系统资源使用。

8. RabbitMQ如何保证高可用

首先,如果要实现RabbitMQ的高可用,单机部署肯定是不合适的,因为单机故障,消息必然无法发送和消费。

因此需要引入集群模式,而集群主要分为三种:

  • 标准集群
  • 镜像集群
  • 联邦集群

1. 标准集群(每个节点只负责一部分数据)
多台RabbitMQ通过网络组成一个集群,所有节点共享元数据(如队列、交换机、绑定等),但一个消息仅存储在单个节点上
在这里插入图片描述
客户端可以连接到集群中的任意节点,因为元数据是共享的,所以任何一个节点都知晓具体消息在哪个节点上,因此可以实现负载均衡。但消息仅会存储在一个节点上不会自动复制到其他节点,所以如果某个节点故障,那么实际上这部分消息就无法消费了,但别的节点还可以提供服务。

2. 镜像集群模式(队列的副本会同步到其他节点上)
相比于标准模式,镜像队列模式下,队列的主副本和一个或多个副本会同步到不同的节点上,即队列的消息会复制到多个节点,如果主队列所在的节点故障,副本节点会自动接管,保证队列的可用性。
在这里插入图片描述

3. Fedrated集群模式(集群之间的数据异地复制)
这其实就是多活模式,主要用于异地的数据复制,例如,在北京上海两个机房都部署RabbitMQ集群,他们之间依赖的RabbitMQ的federation插件实现持续的可靠的AMQP数据通信。
如果北京机房出了故障,上海的机房可以顶上。

9. 为什么RocketMQ不使用Zookeeper作为注册中心,而选择自己实现NameServer

  • 设计简洁且专用:RocketMQ的NameServer设计简单,专门用于RocketMQ的需求,相比于通用的Zookeeper,NameServer更加轻量级且易于部署和维护。
  • 高可用性:RocketMQ的NameServer是无状态的,多个NameServer之间实例对等,可以通过DNS进行负载均衡,而Zookeeper是一个强一致性的系统,对节点之间的同步有严格要求,在某些极端情况下(如网络分区),zookeeper的可用性可能受到影响。
  • 性能优化:NameServer只处理简单的配置和路由消息,不涉及复杂的状态同步和一致性协议,相比于Zookeeper性能更高。
  • 降低依赖性:使用自研的NameServer可以降低对外部系统的依赖。

10. Kafka高性能的原因

  1. 顺序写:磁盘顺序写的性能远远大于随机写的性能
  2. 页缓存:这个主要使用了linux系统底层的一个机制,即Page Cache,又称页缓存,当消息写入到Page Cache后立刻返回,然后等到系统的刷盘进程进行刷盘操作后,页缓存将对应的内容一次性写入磁盘。

之所以快,是因为我们写入内存的速度远远大于写入磁盘的速度,然后我们写入内存之后,再将内存中的东西再 批量一次性写入磁盘,这个过程就是聚集写的过程,从一定程度上减少了IO的次数。

  1. Kafka支持批量接受和发送消息:并且支持消息在压缩之后进行接收和发送,这样从一定程度上减少了网络传输的次数和负担,提高了Kafka消息读取以及消息进行网络传输的效率。
  2. 零拷贝:Kafka的Broker传递数据给消费者的过程使用了零拷贝,底层主要使用了sendfile系统调用,减少了系统用户态和内核态的上下文切换以及数据拷贝,从而提高Kafka数据拷贝的性能。
  3. Kafka采用分段与索引的策略来提高性能,即利用偏移量和时间索引文件实现快速消息查找,从而提高Kafka消息查找的效率。

原文地址:https://blog.csdn.net/weixin_42824596/article/details/142913041

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!