消息队列面试系列-01

1. 什么是消息队列?

MQ全称为Message Queue 消息队列(MQ)是一种应用程序对应用程序的通信方法。

消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。

MQ是消费生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中的消息。

消息生产者只需要把消息发布到MQ中而不用管谁来获取,消息消费者只管从MQ中获取消息而不管是谁发布的消息,这样生产者和消费者双方都不用清楚对方的存在。 

目前在生产环境,使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。

2. 为什么使用消息队列?

消息队列中间件有很多,使用的场景广泛。主要解决的核心问题是削峰填谷、异步处理、模块解耦。

3. RabbitMQ是什么?

RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。

RabbitMQ服务器是用Erlang语言编写的,而群集和故障转移是构建在开放电信平台框架上的。

目前所有主流的编程语言均有与代理接口通讯的客户端库。

4. 消息队列有哪些应用场景?

列举消息队列场景,异步处理,应用解耦,流量削锋,日志处理和消息通讯五个场景。

1、异步处理场景

用户注册后,需要发注册邮件和注册短信。传统的做法有两种

1)串行方式:将注册信息写入数据库成功后,发送注册邮件,再发送注册短信。以上三个任务全部完成后,返回给客户端。

2)并行方式:将注册信息写入数据库成功后,发送注册邮件的同时,发送注册短信。以上三个任务完成后,返回给客户端。与串行的差别是,并行的方式可以提高处理的时间。

按照以上描述,用户的响应时间相当于是注册信息写入数据库的时间,也就是50毫秒。注册邮件,发送短信写入消息队列后,直接返回,因此写入消息队列的速度很快,基本可以忽略,因此用户的响应时间可能是50毫秒。因此采用消息队列的方式,系统的吞吐量提高到每秒20 QPS。比串行提高了3倍,比并行提高了两倍。

2、应用解耦场景

用户购买物品下单后,订单系统需要通知库存系统。传统的做法是订单系统调用库存系统的接口。该模式的缺点:

1)假如库存系统无法访问,则订单减库存将失败,从而导致订单失败;

2)订单系统与库存系统耦合;

如何解决以上问题呢?

订单系统:用户下单后,订单系统完成持久化处理,将消息写入消息队列,返回用户订单下单成功。

库存系统:订阅下单的消息,采用拉/推的方式,获取下单信息,库存系统根据下单信息,进行库存操作。

假如:在下单时库存系统不能正常使用。也不影响正常下单,因为下单后订单系统写入消息队列就不再关心其他的后续操作,从而实现订单系统与库存系统的应用解耦。

3、流量削锋场景

流量削锋也是消息队列中的常用场景,一般在秒杀或团抢活动中被广泛应用。

秒杀活动,一般会因为流量并发过大,导致流量暴增,应用宕机,从而为解决该问题,一般在应用前端加入消息队列。

控制活动的人数,缓解短时间内高流量压垮应用。当用户的请求,服务器接收后,先写入消息队列。如消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面,而其秒杀业务根据消息队列中的请求信息,再做后续处理。

4、日志处理场景

日志处理是指将消息队列用在日志处理中,比如Kafka的应用,解决大量日志传输的问题。日志采集客户端,负责日志数据采集,定时写受写入Kafka队列,而Kafka消息队列,负责日志数据的接收,存储和转发,日志处理应用订阅并消费kafka队列中的日志数据。

5、消息通讯

消息通讯是指消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对点消息队列,或者聊天室等。

5. RabbitMQ 有哪些重要组件?

ConnectionFactory(连接管理器):应用程序与RabbitMQ之间建立连接的管理器

Channel(信道):消息推送使用的通道

Exchange(交换器):用于接受、分配消息

Queue(队列):用于存储生产者的消息

RoutingKey(路由键):用于把生产者的数据分配到交换器上

BindKey(绑定键):用于把交换器的消息绑定到队列上

6. RabbitMQ 有哪些重要角色?

生产者:

消息的生产者,负责创建和推送数据到消息服务器。

消费者:

消息的接收者,用于处理数据和确认消息。

代理:

RabbitMQ本身,用于扮演传递消息的角色,本身并不生产消息。

7. RabbitMQ 如何保证消息顺序性?

RabbitMQ保证消息的顺序性方式有两种:

1)拆分多个queue,每个queue对应一个consumer(消费者),就是多一些queue。

2)一个queue,对应一个consumer(消费者),然后这个consumer内部用内存队列做排队,然后分发给底层不同的worker来处理。

8. 如何保证消息消费的幂等性?

1、利用数据库的唯一约束实现幂等

比如将订单表中的订单编号设置为唯一索引,创建订单时,根据订单编号就可以保证幂等

2、去重表

根据数据库的唯一性约束类似的方式来实现。其实现大体思路是:首先在去重表上建唯一索引,其次操作时把业务表和去重表放在同个本地事务中,如果出现重现重复消费,数据库会抛唯一约束异常,操作就会回滚。

3、利用redis的原子性

每次操作都直接set到redis里面,然后将redis数据定时同步到数据库中。

4、多版本(乐观锁)控制

此方式多用于更新的场景下。其实现的大体思路是:给业务数据增加一个版本号属性,每次更新数据前,比较当前数据的版本号是否和消息中的版本一致,如果不一致则拒绝更新数据,更新数据的同时将版本号+1。

5、状态机机制

此方式多用于更新且业务场景存在多种状态流转的场景。

6、token机制

生产者发送每条数据时,增加一个全局唯一ID,这个ID通常是业务的唯一标识。在消费者消费时,需要验证这个ID是否被消费过,如果没消费过,则进行业务处理。处理结束后,在把这个ID存入Redis,同时设置状态为已消费。如果已经消费过,则清除Redis缓存的这个ID。

9. RabbitMQ 有几种广播类型?

direct(默认方式):最基础最简单的模式,发送方把消息发送给订阅方,如果有多个订阅者,默认采取轮询的方式进行消息发送。

headers:与direct类似,只是性能很差,此类型几乎用不到。

fanout:分发模式,把消费分发给所有订阅者。

topic:匹配订阅模式,使用正则匹配到消息队列,能匹配到的都能接收到。

10. RabbitMQ都有哪些特点?

可靠性

RabbitMQ使用一些机制来保证可靠性,如持久化、传输确认及发布确认等。

灵活的路由

在消息进入队列之前,通过交换器来路由消息。对于典型的路由功能,RabbitMQ己经提供了一些内置的交换器来实现。针对更复杂的路由功能,可以将多个交换器绑定在一起,也可以通过插件机制来实现自己的交换器。

扩展性

多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展集群中节点。

高可用性

队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队列仍然可用。

多种协议

RabbitMQ除了原生支持AMQP协议,还支持STOMP,MQTT等多种消息中间件协议。

多语言客户端

RabbitMQ几乎支持所有常用语言,比如Java、Python、Ruby、PHP、C#、JavaScript等。

管理界面

RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的节点等。

插件机制

RabbitMQ提供了许多插件,以实现从多方面进行扩展,当然也可以编写自己的插件。

11. 如何保证 RabbitMQ 消息队列的高可用?

RabbitMQ有三种模式:单机模式,普通集群模式,镜像集群模式。

单机模式:就是demo级别的,一般是指本地启动MQ,目前几乎没有公司生产中用单机模式。

普通集群模式:意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。

镜像集群模式:这种模式,才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,用户创建的queue,无论元数据(元数据指RabbitMQ的配置数据)还是queue的消息都会存在于多个实例上,然后每次用户写消息到queue时都会自动把消息发送到多个实例的queue中进行消息同步。

12. RabbitMQ 中 broker 和 cluster 分别是指什么?

broker是指一个或多个erlang node的逻辑分组,且node上运行着RabbitMQ应用程序。

cluster是在broker的基础之上,增加了node之间共享元数据的约束。

13. vhost 是什么?有什么作用?

vhost可以理解为虚拟broker,即mini-RabbitMQ server。

其内部均含有独立的queue、exchange和binding等,但最重要的是其拥有独立的权限系统,可以做到vhost范围的用户控制。

当然,从RabbitMQ的全局角度,vhost可以作为不同权限隔离的手段。举一个典型的例子就是不同的应用可以跑在不同的vhost中。

14. RabbitMQ 中消息是基于什么传输?

由于TCP连接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈。

RabbitMQ使用信道的方式来传输数据。

信道是建立在真实的TCP连接内的虚拟连接,且每条TCP连接上的信道数量没有限制。

15. RabbitMQ 中如何解决丢数据的问题?

1、生产者丢数据

生产者的消息没有投递到MQ中怎么办?从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息。

transaction机制就是说,发送消息前,开启事物(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事物就会回滚(channel.txRollback()),如果发送成功则提交事物(channel.txCommit())。

然而缺点就是吞吐量下降了。因此,按照博主的经验,生产上用confirm模式的居多。一旦channel进入confirm模式,所有在该信道上面发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个Ack给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了.如果rabiitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

2、消息队列丢数据

处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步

1)将queue的持久化标识durable设置为true,则代表是一个持久的队列

2)发送消息的时候将deliveryMode=2

这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据。在消息还没有持久化到硬盘时,可能服务已经死掉,这种情况可以通过引入mirrored-queue即镜像队列,但也不能保证消息百分百不丢失(整个集群都挂掉)

3、消费者丢数据

启用手动确认模式可以解决这个问题

1)自动确认模式,消费者挂掉,待ack的消息回归到队列中。消费者抛出异常,消息会不断的被重发,直到处理成功。不会丢失消息,即便服务挂掉,没有处理完成的消息会重回队列,但是异常会让消息不断重试。

2)手动确认模式,如果消费者来不及处理就死掉时,没有响应ack时会重复发送一条信息给其他消费者;如果监听程序处理异常了,且未对异常进行捕获,会一直重复接收消息,然后一直抛异常;如果对异常进行了捕获,但是没有在finally里ack,也会一直重复发送消息(重试机制)。

3)不确认模式,acknowledge="none" 不使用确认机制,只要消息发送完成会立即在队列移除,无论客户端异常还是断开,只要发送完就移除,不会重发。

16. 使用消息队列都有哪些缺点?

1、系统可用性降低

各个系统正常运行,而开发人员增加消息队列插件到项目中,如果此时消息队列服务挂了,那么系统也无法正常运行。因此,系统可用性也就降低了。

2、系统复杂性增加

系统中集成消息队列要考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费、如何保证保证消息可靠传输等问题。因此,需要考虑的各个方面问题更多,增大了系统复杂性。

17. 如何避免消息重复投递或重复消费?

在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id值,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列。

在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,比如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。

针对此类问题,列举处理消息的业务场景:

1、用户获取到消息执行数据库insert插入操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

2、用户获取到消息执行redis缓存set插入操作,不需要解决重复,因为无论set几次结果都是一样的,set操作本来幂等操作。

3、如果上面两种情况还不行,可以考虑使用记录消费。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以Key-Value的形式写入到redis中。当消费者开始消费消息时,首选获取redis中有没消费过该记录。

18. AMQP是什么?

AMQP(Advanced Message Queueing Protocol)协议是一个开放的标准的的协议,它定义了系统之间如何传递消息。

AMQP不仅定义了consumer、producer、broker之间如何交互,也定义了消息的格式和命令的交换。

RabbitMQ就是AMQP协议的Erlang的实现(当然RabbitMQ还支持STOMP2、MQTT3等协议)AMQP的模型架构和RabbitMQ的模型架构是一样的,生产者将消息发送给交换器,交换器和队列绑定。

RabbitMQ中的交换器、交换器类型、队列、绑定、路由键等都是遵循的AMQP协议中相应的概念。

目前RabbitMQ最新版本默认支持的是AMQP0-9-1。

19. AMQP 协议层都有哪些?

Module Layer:协议最高层,主要定义了一些客户端调用的命令,客户端可以用这些命令实现自己的业务逻辑。

Session Layer:中间层,主要负责客户端命令发送给服务器,再将服务端应答返回客户端,提供可靠性同步机制和错误处理。

TransportLayer:最底层,主要传输二进制数据流,提供帧的处理、信道服用、错误检测和数据表示等。

20. AMQP 模型有哪几大组件?

交换器(Exchange)

消息代理服务器中用于把消息路由到队列的组件。

队列(Queue)

用来存储消息的数据结构,位于硬盘或内存中。

绑定(Binding)

一套规则,告知交换器消息应该将消息投递给哪个队列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/644973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue+Element(el-upload+el-form的使用)+springboot

目录 1、编写模板 2、发请求调接口 3、后端返回数据 1.编写实体类 2.Controller类 3、interface接口&#xff08;Service层接口&#xff09; 4.Service&#xff08;接口实现&#xff09; 5、interface接口&#xff08;Mapper层接口&#xff09; 6、xml 4、upload相关参…

前端 防止浏览器提示记住密码以及自动填充密码

当前端 <input /> 的 type’password‘ 时&#xff0c;浏览器为了优化用户体验&#xff0c;会在表单提交后提示用户记住密码 如果不想要这样的行为&#xff0c;最简单的当然是提示用户自己在浏览器设置中进行相关配置 如果希望在代码层面阻止浏览器提示是否记住密码或者…

.git 文件夹结构解析

.git 文件夹结构解析 在这篇文章就让我们来看看这个 Git 仓库里的文件分别都是用来干什么的&#xff0c;以及在执行了相关的 Git 命令后这些文件会如何响应。 hooks&#xff08;钩&#xff09;&#xff1a;存放一些shell脚本info&#xff1a;存放仓库的一些信息logs&#xff…

【git】配置代理访问github

参考大神的方法 没有解决。GitHub访问加速 简直完美&#xff01; github经常Couldn’t connect to server zhangbinDESKTOP-1723CM1 MINGW64 /g/CDN/NET-EQ-DEV $ git clone https://github.com/TaoistKing/AudioPlc.git Cloning into AudioPlc... fatal: unable to access h…

ChromeDriver谷歌驱动最新版安装120/121/122

chromeDriver最新版本下载 最新驱动 https://googlechromelabs.github.io/chrome-for-testing/参考&#xff1a; https://blog.csdn.net/m0_57382185/article/details/134007615

ORM-02-Hibernate 对象关系映射(ORM)框架

拓展阅读 The jdbc pool for java.(java 手写 jdbc 数据库连接池实现) The simple mybatis.&#xff08;手写简易版 mybatis&#xff09; Hibernate Hibernate ORM 允许开发者更轻松地编写那些数据在应用程序进程结束后仍然存在的应用程序。 作为一个对象关系映射&#xff08…

python闭包函数、装饰器、生成器

1. 闭包函数 什么是闭包函数 闭包函数就是在函数内部定义了一个函数&#xff08;内嵌函数&#xff09;&#xff0c;并将这个函数的引用作为返回值返回。 但是闭包函数可以调用外部函数的形参和变量&#xff0c;并且在外部调用闭包函数时&#xff0c;其外部函数的形参和变量仍…

基于蝗虫优化的KNN分类特征选择算法的matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 KNN分类器基本原理 4.2 特征选择的重要性 4.3 蝗虫优化算法&#xff08;GOA&#xff09; 5.完整程序 1.程序功能描述 基于蝗虫优化的KNN分类特征选择算法。使用蝗虫优化算法&#xff…

C++入门语法———命名空间,缺省参数,重载函数

文章目录 一.命名空间1.存在意义2.语法使用1.定义命名空间2.使用命名空间的三种方式 二.缺省参数1.全缺省参数2.半缺省参数 三.重载函数1.定义2.重载原理———名字修饰 一.命名空间 1.存在意义 C命名空间的主要意义是为了避免命名冲突&#xff0c;尤其是在大型项目中可能存在…

“高级SPA项目构建与路由实现“

目录 引言1. SPA项目构建1.1 安装vue-cli,webpack1.2 创建 Vue.js项目1.3 “一问一答”模式1.4 启动项目 2. SPA项目完成路由3. 基于SPA项目完成嵌套路由总结 引言 在现代Web开发中&#xff0c;单页应用&#xff08;SPA&#xff09;已经成为一种流行的开发模式。SPA通过在前端…

(BUUCTF)0ctf_2018_heapstorm2

文章目录 前置知识整体思路house of storm如何进行一次house of stormhouse of storm原理house of storm具体流程 chunk shrink exp 前置知识 unsortedbin attacklargebin attackoff by null构造chunk shrink 整体思路 这道题即是house of storm。除了house of storm&#x…

优优嗨聚:美团代运营服务,为商家赋能,打造流量转化的秘密武器

随着互联网的飞速发展&#xff0c;人们越来越依赖线上平台进行消费。作为国内领先的电商平台之一&#xff0c;美团吸引了众多商家入驻。然而&#xff0c;如何在竞争激烈的美团平台上脱颖而出&#xff0c;成为了商家们面临的一大挑战。此时&#xff0c;美团代运营服务应运而生&a…

html 粒子效果文字特效

有两个代码如下&#xff1a; index.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"> <head>…

HTML5和CSS3的新特性

HTML5的新特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等 1&#xff0c;HTML5新增的语义化标签 <header> 头部标签 <nav> 导航标签 <article> …

《WebKit 技术内幕》学习之九(4): JavaScript引擎

4 实践——高效的JavaScript代码 4.1 编程方式 关于如何使用JavaScript语言来编写高效的代码&#xff0c;有很多铺天盖地的经验分享&#xff0c;以及很多特别好的建议&#xff0c;读者可以搜索相关的词条&#xff0c;就能获得一些你可能需要的结果。同时&#xff0c;本节希望…

记录centos安装nginx过程和问题

今天在centos上安装了nginx&#xff0c;遇到了些问题&#xff0c;记录一下。 使用yum直接安装的话安装的版本是1.20.1&#xff0c;使用源码包安装可以装到1.25.0&#xff08;最新稳定版&#xff09;。很有意思的一点是两种安装方法下安装的路径是不同的&#xff0c;且源码安装…

第一讲:入门知识笔记

python 变量无类型&#xff0c;但值里面有类型。 动态类型语言&#xff08;python&javascript&#xff09;Subtraction num 10 print(num / 2, num // 3, num // -3) # 5.0, 3, -4 向下取整 int(num / 3) # 不用向下取整的办法reverse 3-digit number def res(num):digi…

Java 面向对象案例 03(黑马)

代码&#xff1a; public class phoneTest {public static void main(String[] args) {phone [] arr new phone[3];phone p1 new phone("华为",6999,"白色");phone p2 new phone("vivo",4999,"蓝色");phone p3 new phone("苹…

手把手教你用深度学习做物体检测(一): 快速感受物体检测的酷炫

我们先来看看什么是物体检测&#xff0c;见下图&#xff1a; 如上图所示&#xff0c; 物体检测就是需要检测出图像中有哪些目标物体&#xff0c;并且框出其在图像中的位置。 本篇文章&#xff0c;我将会介绍如何利用训练好的物体检测模型来快速实现上图的效果&#xff0c;这里…

Pyside6中QTableWidget使用

目录 一&#xff1a;介绍&#xff1a; 二&#xff1a;演示 一&#xff1a;介绍&#xff1a; 在 PySide6 中&#xff0c;QTableWidget 是一个用于展示和编辑表格数据的控件。它提供了在窗口中创建和显示表格的功能&#xff0c;并允许用户通过单元格来编辑数据。 要使用 QTabl…