消息队列中间件面试笔记总结RabbitMQ,Kafka,RocketMQ-CSDN博客

(一) Rabbit MQ

RabbitMQ 核心概念

image.png

消息队列的作用

  • 异步
  • 解耦
  • 削峰
    image.png

Exchange(交换器)

在 RabbitMQ 中消息并不是直接被投递到 Queue(消息队列) 中的中间还必须经过 Exchange(交换器) 这一层Exchange(交换器) 会把我们的消息分配到对应的 Queue(消息队列) 中。

Exchange(交换器) 用来接收生产者发送的消息并将这些消息路由给服务器中的队列中如果路由不到或许会返回给 Producer(生产者) 或许会被直接丢弃掉 。这里可以将 RabbitMQ 中的交换器看作一个简单的实体。

RabbitMQ 的 Exchange(交换器) 有 4 种类型不同的类型对应着不同的路由策略direct(默认)fanout, topic, 和 headers不同类型的 Exchange 转发消息的策略有所区别。

image.png

Broker消息中间件的服务节点

对于 RabbitMQ 来说一个 RabbitMQ Broker 可以简单地看作一个 RabbitMQ 服务节点或者 RabbitMQ 服务实例。大多数情况下也可以将一个 RabbitMQ Broker 看作一台 RabbitMQ 服务器。

下图展示了生产者将消息存入 RabbitMQ Broker,以及消费者从 Broker 中消费数据的整个流程。

image.png

这样图 1 中的一些关于 RabbitMQ 的基本概念我们就介绍完毕了下面再来介绍一下 Exchange Types(交换器类型)

如何保证消息的可靠性

消息到 MQ 的过程中搞丢MQ 自己搞丢MQ 到消费过程中搞丢。

  • 生产者到 RabbitMQ事务机制和 Confirm 机制注意事务机制和 Confirm 机制是互斥的两者不能共存会导致 RabbitMQ 报错。
  • RabbitMQ 自身持久化、集群、普通模式、镜像模式。
  • RabbitMQ 到消费者basicAck 机制、死信队列、消息补偿机制。

如何保证 RabbitMQ 消息的顺序性

  • 拆分多个 queue(消息队列)每个 queue(消息队列) 一个 consumer(消费者)就是多一些 queue (消息队列)而已确实是麻烦点
  • 或者就一个 queue (消息队列)但是对应一个 consumer(消费者)然后这个 consumer(消费者)内部用内存队列做排队然后分发给底层不同的 worker 来处理。

如何保证 RabbitMQ 高可用的

RabbitMQ 是比较有代表性的因为是基于主从非分布式做高可用性的我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式单机模式、普通集群模式、镜像集群模式。

普通集群模式

意思就是在多台机器上启动多个 RabbitMQ 实例每个机器启动一个。你创建的 queue只会放在一个 RabbitMQ 实例上但是每个实例都同步 queue 的元数据元数据可以认为是 queue 的一些配置信息通过元数据可以找到 queue 所在实例。
你消费的时候实际上如果连接到了另外一个实例那么那个实例会从 queue 所在实例上拉取数据过来。这方案主要是提高吞吐量的就是说让集群中多个节点来服务某个 queue 的读写操作。

镜像集群模式
在镜像集群模式下你创建的 queue无论元数据还是 queue 里的消息都会存在于多个实例上就是说每个 RabbitMQ 节点都有这个 queue 的一个完整镜像包含 queue 的全部数据的意思。然后每次你写消息到 queue 的时候都会自动把消息同步到多个实例的 queue 上。RabbitMQ 有很好的管理控制台就是在后台新增一个策略这个策略是镜像集群模式的策略指定的时候是可以要求数据同步到所有节点的也可以要求同步到指定数量的节点再次创建 queue 的时候应用这个策略就会自动将数据同步到其他的节点上去了。

好处
你任何一个机器宕机了没事儿其它机器节点还包含了这个 queue 的完整数据别的 consumer 都可以到其它节点上去消费数据。
坏处
第一这个性能开销也太大了吧消息需要同步到所有机器上导致网络带宽压力和消耗很重RabbitMQ 一个 queue 的数据都是放在一个节点里的镜像集群下也是每个节点都放这个 queue 的完整数据。

如何解决消息队列的延时以及过期失效问题

RabbtiMQ 是可以设置过期时间的也就是 TTL。如果消息在 queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在 mq 里而是大量的数据会直接搞丢。我们可以采取一个方案就是批量重导这个我们之前线上也有类似的场景干过。就是大量积压的时候我们当时就直接丢弃数据了然后等过了高峰期以后比如大家一起喝咖啡熬夜到晚上 12 点以后用户都睡觉了。这个时候我们就开始写程序将丢失的那批数据写个临时程序一点一点的查出来然后重新灌入 mq 里面去把白天丢的数据给他补回来。也只能是这样了。假设 1 万个订单积压在 mq 里面没有处理其中 1000 个订单都丢了你只能手动写程序把那 1000 个订单给查出来手动发到 mq 里去再补一次。

消息堆积问题怎么解决

我在实际的开发中没遇到过这种情况不过如果发生了堆积的问题解决方案也所有很多的
第一:提高消费者的消费能力 ,可以使用多线程消费任务
第二增加更多消费者提高消费速度使用工作队列模式, 设置多个消费者消费消费同一个队列中的消息
第三扩大队列容积提高堆积上限可以使用RabbitMQ惰性队列惰性队列的好处主要是

①接收到消息后直接存入磁盘而非内存

②消费者要消费消息时才会从磁盘中读取并加载到内存

③支持数百万条的消息存储

(二) kafka

Kafka 是一个 高吞吐量 的、 持久性 的、 分布式 发布订阅消息系统

  • 高吞吐量可以满足每秒百万级别消息的生产和消费。
    Kafka的数据还是放在磁盘里面的主要是Kafka利用了磁盘顺序读写速度超过内存随机读写速度这个特性。
    所以说它的吞吐量才这么高
  • 持久性有一套完善的消息存储机制确保数据高效安全的持久化。
  • 分布式它是基于分布式的扩展、和容错机制Kafka的数据都会复制到几台服务器上。当某一台机器故障失效时生产者和消费者切换使用其它的机器。

Kafka的数据时存储是磁盘中的为什么可以满足每秒百万级别消息的生产和消费

kafka利用了磁盘顺序读写速度超过内存随机读写速度这个特性。
Kafka主要应用在实时计算领域可以和Flume、Spark、Flink等框架结合在一块使用

组件介绍

image.png

这个Kafka集群内有两个节点这些节点在这里我们称之为Broker

  • Broker消息的代理Kafka集群中的一个节点称为一个broker
    在Kafka中有Topic的概念
  • Topic称为主题Kafka处理的消息的不同分类(是一个逻辑概念)。
    如果把Kafka认为是一个数据库的话那么Kafka中的Topic就可以认为是一张表不同的topic中存储不同业务类型的数据方便使用在Topic内部有partition的概念
  • Partition是Topic物理上的分组一个Topic会被分为1个或者多个partition(分区)分区个数是在创建topic的时候指定。每个topic都是有分区的至少1个。
    注意这里面针对partition其实还有副本的概念主要是为了提供数据的容错性我们可以在创建Topic的时候指定partition的副本因子是几个。在这里面副本因子其实就是2了其中一个是Leader另一个是真正的副本Leader中的这个partition负责接收用户的读写请求副本partition负责从Leader里面的partiton中同步数据这样的话如果后期leader对应的节点宕机了副本可以切换为leader顶上来。在partition内部还有一个message的概念
  • Message我们称之为消息代表的就是一条数据它是通信的基本单位每个消息都属于一个
    partition。

(三) RocketMQ

核心概念

  • NameServer可以理解为是一个注册中心主要是用来保存topic路由信息管理Broker。在NameServer的集群中NameServer与NameServer之间是没有任何通信的。
  • Broker核心的一个角色主要是用来保存topic的信息接受生产者产生的消息持久化消息。在一个Broker集群中相同的BrokerName可以称为一个Broker组一个Broker组中,BrokerId为0的为主节点其它的为从节点。BrokerName和BrokerId是可以在Broker启动时通过配置文件配置的。每个Broker组只存放一部分消息。
  • 生产者生产消息的一方就是生产者
  • 生产者组一个生产者组可以有很多生产者只需要在创建生产者的时候指定生产者组那么这个生产者就在那个生产者组
  • 消费者用来消费生产者消息的一方
  • 消费者组跟生产者一样每个消费者都有所在的消费者组一个消费者组可以有很多的消费者不同的消费者组消费消息是互不影响的。
  • topic主题 可以理解为一个消息的集合的名字生产者在发送消息的时候需要指定发到哪个topic下消费者消费消息的时候也需要知道自己消费的是哪些topic底下的消息。
  • Tag子主题 比topic低一级可以用来区分同一topic下的不同业务类型的消息发送消息的时候也需要指定。

其实对于主题模型的实现来说每个消息中间件的底层设计都是不一样的就比如 Kafka 中的 分区 RocketMQ 中的 队列 RabbitMQ 中的 Exchange 。我们可以理解为 主题模型/发布订阅模型 就是一个标准那些中间件只不过照着这个标准去实现而已。

所以RocketMQ 中的 主题模型 到底是如何实现的呢首先我画一张图大家尝试着去理解一下。

image.png

我们可以看到在整个图中有 Producer GroupTopicConsumer Group 三个角色我来分别介绍一下他们。

  • Producer Group 生产者组代表某一类的生产者比如我们有多个秒杀系统作为生产者这多个合在一起就是一个 Producer Group 生产者组它们一般生产相同的消息。
  • Consumer Group 消费者组代表某一类的消费者比如我们有多个短信系统作为消费者这多个合在一起就是一个 Consumer Group 消费者组它们一般消费相同的消息。
  • Topic 主题代表一类消息比如订单消息物流消息等等。

你可以看到图中生产者组中的生产者会向主题发送消息而 主题中存在多个队列生产者每次生产消息之后是指定主题中的某个队列发送消息的。

RocketMQ的架构图

image.png

工作流程

image.png

  • Broker启动的时候会往每台NameServer因为NameServer之间不通信所以每台都得注册注册自己的信息这些信息包括自己的ip和端口号自己这台Broker有哪些topic等信息。
  • Producer在启动之后会跟会NameServer建立连接定期从NameServer中获取Broker的信息当发送消息的时候会根据消息需要发送到哪个topic去找对应的Broker地址如果有的话就向这台Broker发送请求没有找到的话就看根据是否允许自动创建topic来决定是否发送消息。
  • Broker在接收到Producer的消息之后会将消息存起来持久化如果有从节点的话也会主动同步给从节点实现数据的备份
  • Consumer启动之后也会跟会NameServer建立连接定期从NameServer中获取Broker和对应topic的信息然后根据自己需要订阅的topic信息找到对应的Broker的地址然后跟Broker建立连接获取消息进行消费.
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: RabbitMQ