1. 什么事消息队列

  • 消息队列(Message Queue)是一种用在应用程序之间传递消息的通信方式,消息队列允许应用程序异步地发送和接收消息,并不需要直接连接到对方。
  • 消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象
  • 队列(Queue)可以说是一个数据结构,可以储存数据。先进先出

2. 队列有哪些作用和应用场景

2.1应用解耦

3. 认识一下RabbitMQ

​ 一款基于AMQP(高级消息队列协议)用于软件之间的通信中间件,由Rabbit科技有限公司开发,服务端用Erlang语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等。用于在分布式系统中储存转发消息,在易用性、扩展性、高可用性等方面表现不俗。

​ RabbitMQ四大核心:

  • 生产者
  • 消费者
  • 队列
  • 交换机

​ AMQP协议是一种二进制协议,它定义了一组规则和标准,以确保消息可以在不同应用程序和平台之间传递和解释,AMQP协议包含四个核心组件:

  • 消息
  • 交换机
  • 队列
  • 绑定

4. RabbitMQ的安装

代码 略

5.RabbitMQ的工作原理

Broker:接收和分发消息的应用,RabbitMQ Server 就是 Message Broker

Virtual host:Virtual host 是一个虚拟主机的概念,一个Broker中可以有多个Virtual host,每个Virtual host都有一套自己的Exchange和Queue,同一个Virtual host中的Exchange和Queue不能重名,不同的Virtual host中的Exchange和Queue名字可以一样。这样,不同用户在访问同一个Rabbit Broker时,可以创建自己单独的Virtual host,然后在自己的Virtual host中创建Exchange和Queue,很好的做到了不同用户之间相互隔离的效果。

Connection:publisher/consumer和broker之间的TCP链接

Channel:发送消息的通道,如果每一次访问RabbitMQ都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也低。Channel实在Connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id 帮助客户端和 message broker识别channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销

Exchange:message打到broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到queue中去。常用的类型有:direct(point-to-point),topic(publish-subscribe),fanout(multicast)

Queue:Queue是一个用来存放消息的队列,生产者发送到消息会被放到Queue中,消费者消费消息也是从Queue中取走消息。

Binding:echange和queue之间虚拟链接,binding中可以包含routing key,binding信息被保存到exchange中的查询表中,用于message的分发依据

6.如何实现生产者和消费者

代码 略

7.RabbitMQ交换机类型

7.1 direct

​ 路由键与列名完全匹配交换机,这种类型交换机,通过RoutingKey路由键将交换机和队列进行绑定,消息被发送打exchange是,需要根据消息的RoutingKey,来进行匹配,只讲消息发送到完全匹配到此RoutingKey的队列

​ 比如:如果一个队列绑定到交换机要求路由键为"key",则只转发RoutingKey标记为"Key"的消息,不会转发"key1",等等。他是完全匹配、单播的模式

​ 同一个key可以绑定多个Queue队列;当匹配到key是,Queue1和Queue2都可以收到消息

7.2 fanout

​ fanout,扇出类型交换机,此种交换机,会将消息分发给所有绑定了次交换机的队列,此时RoutingKey参数无效。

​ fanout类型交换机下发送消息一条,无论RoutingKey是什么,queue1,queue2,queue3都可以收到消息

7.3 topic

​ topic,主题类型交换机,此种交换机与direct类似,也是需要通过RoutingKey进行匹配分发,区别在于topic可以进行模糊匹配,direct是完全匹配。

  1. topic中,将RoutingKey通过"."来分为多个部分
  2. "*":代表一个部分
  3. "#":代表0个或多个部分(如果绑定的路由键位"#"时,则接受所有消息,因为路由键都匹配)

​ 然后发送消息信息,RoutingKey为"key1.key2.key3.key4",将这个路由键分为了4个部分,此条路由键,将会匹配:

  1. key1.key2.key3.;成功匹配,因为 可以代表一个部分
  2. key1.#:成功匹配,因为#可以代表0或多个部分
  3. *.key2.*.key4:成功匹配,因为第一和第三部分分别为key1和key3,且为4个部分,刚好匹配
  4. #.key3.key4:成功匹配,#可以代表多个部分,正好匹配中了我们的key1和key2

​ 如果发送消息RoutingKey为"key1",那么将只能匹配中key1.#,#可以代表0个部分

7.4 header

​ hearder匹配AMQP消息的header而不是路由键,此外headers交换器和direct交换器完全一致,但性能差很多,目前几乎用不到了

消费方指定的headers中必须包含一个"x-match"的键。

键"x-match"的值有两个

  1. x-match = all:表示所有键值都匹配到才能接受消息
  2. x-match = any:表示只要有键值对匹配就能接收到消息

发送消息时间,如果其它参数信息是{"name":"xiaochuanXX","sex":"男“},因为queue2的x-match是any,只需要一个键值对匹配就能接收到消息,所以queue2可以接收到消息,queue1的x-match是all,需要所有的键值对都匹配才能收到消息,所有此刻queue1接收不到消息

8.RabbitMQ集群

11. 消息队列面试题

11.2使用消息队列有什么缺点

  • 降低系统的可用性:系统引入的外部依赖越多,越容易挂掉
  • 系统复杂度提高:使用MQ后可能需要保证消息没有被重复消费、处理消息丢失的情况、保证消息传递的顺序性等等问题;
  • 一致性问题:A系统处理完了直接返回成功了,但问题是:要是B、C、D三个系统哪里,B和D两个系统写库成功了,结果C系统写库失败了,就造成数据不一致了

11.3如果保证消息队列的顺序性

  • 生产者有序的情况下,单线程消费来保证消息的顺序性
  • 生产者无序的情况下,对消息进行编号,消费者处理事根据编号判断顺序。多个消费者,可以考虑增加分布式锁

11.4如果保证消息不被重复消费/如何

...

Last modification:October 25, 2023
如果觉得我的文章对你有用,请收藏本站