首页
题库
公司真题
专项练习
面试题库
在线编程
面试
面试经验
AI 模拟面试
简历
求职
学习
基础学习课
实战项目课
求职辅导课
专栏&文章
竞赛
搜索
我要招人
发布职位
发布职位、邀约牛人
更多企业解决方案
AI面试、笔试、校招、雇品
HR免费试用AI面试
最新面试提效必备
登录
/
注册
别问了别问了答不出来了
门头沟学院 后端工程师
发布于湖北
关注
已关注
取消关注
mark
@大彬聊编程:
三天吃透消息队列面试八股文
本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~Github地址:https://github.com/Tyson0314/Java-learning为什么要使用消息队列?总结一下,主要三点原因:解耦、异步、削峰。1、解耦。比如,用户下单后,订单系统需要通知库存系统,假如库存系统无法访问,则订单减库存将失败,从而导致订单操作失败。订单系统与库存系统耦合,这个时候如果使用消息队列,可以返回给用户成功,先把消息持久化,等库存系统恢复后,就可以正常消费减去库存了。2、异步。将消息写入消息队列,非必要的业务逻辑以异步的方式运行,不影响主流程业务。3、削峰。消费端慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的。比如秒杀活动,一般会因为流量过大,从而导致流量暴增,应用挂掉。这个时候加上消息队列,服务器接收到用户的请求后,首先写入消息队列,如果消息队列长度超过最大数量,则直接抛弃用户请求或跳转到错误页面。使用了消息队列会有什么缺点系统可用性降低。引入消息队列之后,如果消息队列挂了,可能会影响到业务系统的可用性。系统复杂性增加。加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。常见的消息队列对比吞吐量万级的 ActiveMQ 和 RabbitMQ 的吞吐量(ActiveMQ 的性能最差)要比 十万级甚至是百万级的 RocketMQ 和 Kafka 低一个数量级。可用性都可以实现高可用。ActiveMQ 和 RabbitMQ 都是基于主从架构实现高可用性。RocketMQ 基于分布式架构。 kafka 也是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用时效性RabbitMQ 基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。其他三个都是 ms 级。功能支持除了 Kafka,其他三个功能都较为完备。 Kafka 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准消息丢失ActiveMQ 和 RabbitMQ 丢失的可能性非常低, RocketMQ 和 Kafka 理论上不会丢失。总结:ActiveMQ 的社区算是比较成熟,但是较目前来说,ActiveMQ 的性能比较差,而且版本迭代很慢,不推荐使用。RabbitMQ 在吞吐量方面虽然稍逊于 Kafka 和 RocketMQ ,但是由于它基于 erlang 开发,所以并发能力很强,性能极其好,延时很低,达到微秒级。但是也因为 RabbitMQ 基于 erlang 开发,所以国内很少有公司有实力做 erlang 源码级别的研究和定制。如果业务场景对并发量要求不是太高(十万级、百万级),那这四种消息队列中,RabbitMQ 一定是你的首选。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。RocketMQ 阿里出品,Java 系开源项目,源代码我们可以直接阅读,然后可以定制自己公司的 MQ,并且 RocketMQ 有阿里巴巴的实际业务场景的实战考验。RocketMQ 社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准 JMS 规范走的有些系统要迁移需要修改大量代码。还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用 RocketMQ 挺好的Kafka 的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms 级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展。同时 kafka 最好是支撑较少的 topic 数量即可,保证其超高吞吐量。kafka 唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略这个特性天然适合大数据实时计算以及日志收集。如何保证消息队列的高可用?RabbitMQ:镜像集群模式RabbitMQ 是基于主从做高可用性的,Rabbitmq有三种模式:单机模式、普通集群模式、镜像集群模式。单机模式一般在生产环境中很少用,普通集群模式只是提高了系统的吞吐量,让集群中多个节点来服务某个 Queue 的读写操作。那么真正实现 RabbitMQ 高可用的是镜像集群模式。镜像集群模式跟普通集群模式不一样的是,创建的 Queue,无论元数据还是Queue 里的消息都会存在于多个实例上,然后每次你写消息到 Queue 的时候,都会自动和多个实例的 Queue 进行消息同步。这样设计,好处在于:任何一个机器宕机不影响其他机器的使用。坏处在于:1. 性能开销太大:消息同步所有机器,导致网络带宽压力和消耗很重;2. 扩展性差:如果某个 Queue 负载很重,即便加机器,新增的机器也包含了这个 Queue 的所有数据,并没有办法线性扩展你的 Queue。Kafka:partition 和 replica 机制Kafka 基本架构是多个 broker 组成,每个 broker 是一个节点。创建一个 topic 可以划分为多个 partition,每个 partition 可以存在于不同的 broker 上,每个 partition 就放一部分数据,这就是天然的分布式消息队列。就是说一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。Kafka 0.8 以前,是没有 HA 机制的,任何一个 broker 宕机了,它的 partition 就没法写也没法读了,没有什么高可用性可言。Kafka 0.8 以后,提供了 HA 机制,就是 replica 副本机制。每个 partition 的数据都会同步到其他机器上,形成自己的多个 replica 副本。然后所有 replica 会选举一个 leader 出来,生产和消费都跟这个 leader 打交道,然后其他 replica 就是 follower。写的时候,leader 会负责把数据同步到所有 follower 上去,读的时候就直接读 leader 上数据即可。Kafka 会均匀的将一个 partition 的所有 replica 分布在不同的机器上,这样才可以提高容错性。MQ常用协议AMQP协议 AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。优点:可靠、通用MQTT协议 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统STOMP协议 STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。优点:命令模式(非topic/queue模式)XMPP协议 XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大其他基于TCP/IP自定义的协议:有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。MQ的通讯模式点对点通讯:点对点方式是最为传统和常见的通讯方式,它支持一对一、一对多、多对多、多对一等多种配置方式,支持树状、网状等多种拓扑结构。多点广播:MQ适用于不同类型的应用。其中重要的,也是正在发展中的是"多点广播"应用,即能够将消息发送到多个目标站点(Destination List)。可以使用一条MQ指令将单一消息发送到多个目标站点,并确保为每一站点可靠地提供信息。MQ不仅提供了多点广播的功能,而且还拥有智能消息分发功能,在将一条消息发送到同一系统上的多个用户时,MQ将消息的一个复制版本和该系统上接收者的名单发送到目标MQ系统。目标MQ系统在本地复制这些消息,并将它们发送到名单上的队列,从而尽可能减少网络的传输量。发布/订阅(Publish/Subscribe)模式:发布/订阅功能使消息的分发可以突破目的队列地理指向的限制,使消息按照特定的主题甚至内容进行分发,用户或应用程序可以根据主题或内容接收到所需要的消息。发布/订阅功能使得发送者和接收者之间的耦合关系变得更为松散,发送者不必关心接收者的目的地址,而接收者也不必关心消息的发送地址,而只是根据消息的主题进行消息的收发。在MQ家族产品中,MQ Event Broker是专门用于使用发布/订阅技术进行数据通讯的产品,它支持基于队列和直接基于TCP/IP两种方式的发布和订阅。集群(Cluster):为了简化点对点通讯模式中的系统配置,MQ提供 Cluster 的解决方案。集群类似于一个 域(Domain) ,集群内部的队列管理器之间通讯时,不需要两两之间建立消息通道,而是采用 Cluster 通道与其它成员通讯,从而大大简化了系统配置。此外,集群中的队列管理器之间能够自动进行负载均衡,当某一队列管理器出现故障时,其它队列管理器可以接管它的工作,从而大大提高系统的高可靠性如何保证消息的顺序性?RabbitMQ拆分多个 Queue,每个 Queue一个 Consumer;或者就一个 Queue 但是对应一个 Consumer,然后这个 Consumer 内部用内存队列做排队,然后分发给底层不同的 Worker 来处理。Kafka一个 Topic,一个 Partition,一个 Consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。写 N 个内存 Queue,具有相同 key 的数据都到同一个内存 Queue;然后对于 N 个线程,每个线程分别消费一个内存 Queue 即可,这样就能保证顺序性。如何避免消息重复消费?在消息生产时,MQ内部针对每条生产者发送的消息生成一个唯一id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列。在消息消费时,要求消息体中也要有一全局唯一id作为去重和幂等的依据,避免同一条消息被重复消费。大量消息在 MQ 里长时间积压,该如何解决?一般这个时候,只能临时紧急扩容了,具体操作步骤和思路如下:先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉;新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量;然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue;接着临时用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据;等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。MQ 中的消息过期失效了怎么办?如果使用的是RabbitMQ的话,RabbtiMQ 是可以设置过期时间的(TTL)。如果消息在 Queue 中积压超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。这时的问题就不是数据会大量积压在 MQ 里,而是大量的数据会直接搞丢。这个情况下,就不是说要增加 Consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。我们可以采取一个方案,就是批量重导。就是大量积压的时候,直接将数据写到数据库,然后等过了高峰期以后将这批数据一点一点的查出来,然后重新灌入 MQ 里面去,把丢的数据给补回来。消息中间件如何做到高可用?以Kafka为例。Kafka 的基础集群架构,由多个broker组成,每个broker都是一个节点。当你创建一个topic时,它可以划分为多个partition,而每个partition放一部分数据,分别存在于不同的 broker 上。也就是说,一个 topic 的数据,是分散放在多个机器上的,每个机器就放一部分数据。每个partition放一部分数据,如果对应的broker挂了,那这部分数据是不是就丢失了?那不是保证不了高可用吗?Kafka 0.8 之后,提供了复制多副本机制来保证高可用,即每个 partition 的数据都会同步到其它机器上,形成多个副本。然后所有的副本会选举一个 leader 出来,让leader去跟生产和消费者打交道,其他副本都是follower。写数据时,leader 负责把数据同步给所有的follower,读消息时,直接读 leader 上的数据即可。如何保证高可用的?就是假设某个 broker 宕机,这个broker上的partition 在其他机器上都有副本的。如果挂的是leader的broker呢?其他follower会重新选一个leader出来。如何保证数据一致性,事务消息如何实现?一条普通的MQ消息,从产生到被消费,大概流程如下:生产者产生消息,发送带MQ服务器MQ收到消息后,将消息持久化到存储系统。MQ服务器返回ACk到生产者。MQ服务器把消息push给消费者消费者消费完消息,响应ACKMQ服务器收到ACK,认为消息消费成功,即在存储中删除消息。举个下订单的例子吧。订单系统创建完订单后,再发送消息给下游系统。如果订单创建成功,然后消息没有成功发送出去,下游系统就无法感知这个事情,出导致数据不一致。如何保证数据一致性呢?可以使用事务消息。一起来看下事务消息是如何实现的吧。生产者产生消息,发送一条半事务消息到MQ服务器MQ收到消息后,将消息持久化到存储系统,这条消息的状态是待发送状态。MQ服务器返回ACK确认到生产者,此时MQ不会触发消息推送事件生产者执行本地事务如果本地事务执行成功,即commit执行结果到MQ服务器;如果执行失败,发送rollback。如果是正常的commit,MQ服务器更新消息状态为可发送;如果是rollback,即删除消息。如果消息状态更新为可发送,则MQ服务器会push消息给消费者。消费者消费完就回ACK。如果MQ服务器长时间没有收到生产者的commit或者rollback,它会反查生产者,然后根据查询到的结果执行最终状态。如何设计一个消息队列?首先是消息队列的整体流程,producer发送消息给broker,broker存储好,broker再发送给consumer消费,consumer回复消费确认等。producer发送消息给broker,broker发消息给consumer消费,那就需要两次RPC了,RPC如何设计呢?可以参考开源框架Dubbo,你可以说说服务发现、序列化协议等等broker考虑如何持久化呢,是放文件系统还是数据库呢,会不会消息堆积呢,消息堆积如何处理呢。消费关系如何保存呢? 点对点还是广播方式呢?广播关系又是如何维护呢?zk还是config server消息可靠性如何保证呢?如果消息重复了,如何幂等处理呢?消息队列的高可用如何设计呢? 可以参考Kafka的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。消息事务特性,与本地业务同个事务,本地消息落库;消息投递到服务端,本地才删除;定时任务扫描本地消息库,补偿发送。MQ得伸缩性和可扩展性,如果消息积压或者资源不够时,如何支持快速扩容,提高吞吐?可以参照一下 Kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了吗。参考链接多线程异步和MQ的区别CPU消耗。多线程异步可能存在CPU竞争,而MQ不会消耗本机的CPU。MQ 方式实现异步是完全解耦的,适合于大型互联网项目。削峰或者消息堆积能力。当业务系统处于高并发,MQ可以将消息堆积在Broker实例中,而多线程会创建大量线程,甚至触发拒绝策略。使用MQ引入了中间件,增加了项目复杂度和运维难度。总的来说,规模比较小的项目可以使用多线程实现异步,大项目建议使用MQ实现异步。
点赞 5
评论 0
全部评论
推荐
最新
楼层
暂无评论,快来抢首评~
相关推荐
昨天 22:41
门头沟学院 Java
携程sp、途虎ssp、科大讯飞ssp、小红书、群核offer来时路
投递携程等公司10个岗位
点赞
评论
收藏
分享
12-23 13:26
门头沟学院 前端工程师
字节生活服务前端一面
全程2小时,拷打很深,自己准备不是很充分,面试体验还是不错的,给了很多对我简历和学习路线的建议,很受用-项目经历1、问了项目经历,一些指标和性能监控2、项目里websocket和轮询怎么使用的?3、项目里的性能优化怎么做的,lazy load和具体渲染时间等指标?-八股1、浏览器渲染流程?2、重排跟重绘的区别,哪个性能比较好?3、浏览器缓存?4、前端有哪些本地存储方式?5、跨域问题怎么解决的?6、CSS的模块化?怎么保证样式不冲突?7、组件间通信方式?8、Vue2和Vue3的区别?9、虚拟DOM对性能的影响?-手撕1、看一段赋值的代码输出2、hot100大数相加
点赞
评论
收藏
分享
12-19 18:09
景德镇艺术职业大学 Java
这种简历有机会进大厂实习吗
程序员花海:
实习和校招简历正确格式应该是教育背景+实习+项目经历+个人评价 其中项目经历注意要体现业务 实习经历里面的业务更是要自圆其说 简历模板尽可能保持干净整洁 不要太花哨的
点赞
评论
收藏
分享
10-29 15:51
嘉应学院 Java
投Java后端实习,一直没有面试,简历有什么问题吗
是因为学历不好,只是二本吗?
后端转测开第一人:
你把简历的学历改成北京交通大学 去海投1000份发现基本还是没面试
点赞
评论
收藏
分享
12-24 21:05
门头沟学院 自动化
大学废物离开优绩主义之后发现外面根本没下雨
2025年马上结束了,这一年真的经历了很多,有了自己的第一次实习,谈上了一段非常美好的恋爱,秋招也取得了自己满意的成果,这一年虽然马不停蹄陀螺般旋转,但结果让人十分满意。回想起这一年乃至过去的三年大学时光,总觉得之前的一切担忧和焦虑其实都是被刻意营造出来的。如果你愿意听我的故事...楼主来自山河四省的一个小县城,高中是衡水式管理,但我比较佛系和摆烂,平常就是一个末流211的水平,高考走了狗屎运来到了ip地末九读了自动化类的专业,由于中学时候就比较摆,更没有珍惜大学的生活,要么出去玩,要么在宿舍打游戏,要么跑跑步运动运动,总之除了学习啥都干,大一疫情还没挂科,回来之后大一下学期开始频繁挂科,第二...
过期的小熊软糖:
恭喜恭喜
2025年终总结
点赞
评论
收藏
分享
评论
点赞成功,聊一聊 >
点赞
收藏
分享
评论
提到的真题
返回内容
全站热榜
更多
1
...
工作半年后更确定:我们依然不欠优绩主义什么
6733
2
...
我建了一个分享实习业务的仓库,欢迎大家贡献哦
2527
3
...
牛客2025年终报告重磅上线——揭晓你的年度修炼成就!
2398
4
...
#牛客2025仙途报告#居然是五颗星
2270
5
...
【2025-年终总结】25届毕业生果果牛这一年~
1962
6
...
一个程序员的自救书|从酒吧陪玩DM到上岸大厂
1803
7
...
牛客年终报告,今日道爷我成了
1780
8
...
腾讯 微信支付一面面经
1772
9
...
28第二次面试
1326
10
...
在当下这个社会,在人生这个无常的时代,我真心希望你和各位牛友开心
1209
创作者周榜
更多
正在热议
更多
#
牛客2025仙途报告
#
10693次浏览
220人参与
#
我们是不是被“优绩主义”绑架了?
#
1195次浏览
53人参与
#
2025年终总结
#
190121次浏览
3200人参与
#
找工作,行业重要还是岗位重要?
#
86854次浏览
1736人参与
#
你面试体验感最差/最好的公司
#
27291次浏览
455人参与
#
今年你最想重开的一场面试是?
#
10272次浏览
119人参与
#
礼物开箱Plog
#
2822次浏览
99人参与
#
为了秋招你都做了哪些准备?
#
29466次浏览
524人参与
#
一人说一个提前实习的好处
#
19554次浏览
287人参与
#
秋招落幕,你是He or Be
#
20813次浏览
362人参与
#
机械人晒出你的简历
#
147825次浏览
883人参与
#
重来一次,你会对开始求职的自己说
#
9322次浏览
234人参与
#
工作中听到最受打击的一句话
#
11528次浏览
169人参与
#
实习没事做是福还是祸?
#
22224次浏览
328人参与
#
工作两年,想和老板谈涨薪怎么说
#
39058次浏览
176人参与
#
离家近房租贵VS离家远但房租低,怎么选
#
13902次浏览
130人参与
#
25届暑期实习
#
1039132次浏览
20592人参与
#
实习的内耗时刻
#
212565次浏览
1579人参与
#
拿到offer之后,可以做些什么
#
81342次浏览
431人参与
#
这些公司卡简历很严格
#
82614次浏览
375人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务