当前位置: 首页 > 科技观察

面试官提问:说说你对消息队列的理解

时间:2023-03-22 02:06:08 科技观察

本文转载自微信公众号《Java极客技术》,作者鸭血范。转载本文请联系Java极客技术公众号。关于消息队列,断断续续看了很多资料,一直想抽点时间整理记录一下这方面的知识,但是一直没抽出时间写。刚好我所在的项目在实际业务中用到了消息队列,所以就简单说一下。整理一下知识点,可能有些理解不到位的地方,希望网友们批评指正!1、消息队列的由来在你了解消息队列之前可能听过很多概念,比如JMS、AMQP、ActiveMQ、RabbitMQ、RocketMQ、Kafka等。一个消息中间件,为什么要搞出那么多概念呢?别慌,我们从历史的角度来理清这些MQ和协议的关系!消息中间件诞生的时间很早,在互联网应用还很贫瘠的时候,美国的一个印度兄弟VivekRanadive就设想了一个通用的软件总线,采用发布-订阅的模式,类似于电脑主板上的总线。如果一个新的设备或程序要与电脑上的其他设备软件进行通信,只需要按照协议对接总线即可完成访问和通信!1983年,26岁的印度兄弟VivekRanadive创立了Teknekron公司,实现了世界上第一个消息中间件TheInformationBus(TIB)。很快TIB软件就受到了企业的欢迎,最初被高盛集团用来解决金融交易问题。Teknekron的业务发展速度甚至引起了当时最强大的IT公司IBM的注意。于是IBM也开始组队开发自己的消息队列软件,这才有了后来的wespheremq,很快微软也加入了战团。由于商业壁垒,各个软件厂商按照自己的标准来实现软件通信,这就避免了企业客户随便更换MQ平台。为了打破这个障碍,让消息能够在各种消息队列平台之间进行通信,JMS(JavaMessageService)应运而生。JMS试图通过提供一个公共的JavaAPI来隐藏各个MQ产品供应商提供的实现接口,从而跨越障碍,解决互操作性问题。从技术上讲,Java应用程序只需要针对JMSAPI进行编程并选择合适的MQ驱动程序即可。JMS将负责其他部分,就像JDBC一样。对于开发者来说,只需要写sql,具体是使用oracle,mysql还是sqlserver,具体厂商可以提供驱动包文件,开发者不需要关心具体的数据库厂商,大大提高了开发效率效率,降低开发难度。ActiveMQ是JMS的具体实现。JMS-点对点模型JMS-点对点模型JMS-发布-订阅模型JMS-发布-订阅模型虽然使用标准化接口可以有效地集成许多不同的MQ产品,但也暴露出许多问题。例如,某些MQ产品提供了非常高级的功能。但由于标准化接口的限制,用户无法使用,因此迫切需要一种新的标准化消息通信解决方案。2006年6月,Cisco、Redhat、iMatix等共同制定了AMQP的开放标准,AMQP由此走上历史舞台。AMQP是一个应用层协议的开放标准,解决了很多消息中间件的需求和拓扑问题。它是为面向消息的中间件设计的。基于该协议的客户端和消息中间件可以传输消息,不受产品、开发语言等方面的限制。JMSvsAMQPRabbitMQ是AMQP的具体实现。AMQP-Model随着时间的推进,虽然AMQP规范可以应用于很多业务场景,但是领英(LinkedIn)在实现消息队列的时候觉得AMQP规范并不适合自己,所以在设计Kafka的时候,并没有支持AMQP所有功能。同时阿里巴巴的RocketMQ在实现上也借鉴了Kakfa的思路,不支持AMQP协议,你会发现Kafka和RocketMQ中有类似Topic和ConsumerGroup的概念,但是这些概念在Kafka和RocketMQ中是不存在的AMQP协议。.2、为什么要使用消息队列虽然消息中间件已经发展了很多年,但是并不是每个项目都有机会接触到消息队列。对于刚接触MQ的同学来说,难免会提出一些问题!什么是消息队列?为什么要使用消息队列?使用消息队列有什么缺点?对于传统的应用,如果需要向另一个应用发送信息,只需要向它发送一个请求即可!这种方法简单直接,但是如果应用2突然挂掉了,应用1可能会因为服务异常而无法继续提供服务!想象在应用1和应用2之间插入一个消息服务,主要用来接收和发送消息,这样应用1和应用2之间的依赖关系就解耦了,同时任何一方都不能继续提供服务不可用时的服务!插入的消息服务称为消息队列!可见消息队列的引入带来的好处是显而易见的:程序解耦:应用1和应用2交互时,不会因为一个服务中断而停止服务;异步处理:程序解耦后,最大的好处就是可以异步处理,应用1只需要将消息发送给消息中间件,应用2只需要从消息中间件接收消息然后处理即可;同时,基于异步处理的特点,在一些业务场景中,比如商品秒杀活动,引入消息队列后,在客户端请求量大的时候,可以有效的砍掉流量高峰!如果没有中间层做缓冲,在进行商品闪购时,突然涌入的大量请求很可能会导致系统直接瘫痪。甚至停机!在一个大型的网站系统中,如何通过实时的日志快速定位系统的异常代码可以说是非常重要的!LinkedIn开发的消息队列Kafka可以说是日志采集之王。在中大型系统开发中,在日志处理中使用消息队列Kafka可以有效解决海量日志传输问题。当然,引入消息队列也会带来明显的缺点:系统可用性降低:引入消息队列之前,不用考虑消息丢失或者消息队列服务挂掉等情况,但是引入消息队列之后,你需要考虑这些问题!系统复杂度增加:加入消息队列后,需要保证消息不被重复消费,对消息的处理不正确等等!虽然引入消息队列会带来一些问题,但是俗话说,兵来将挡,水要躲,这句话同样适用于IT开发人员,有坑要填!对于系统可用性的降低,通常的解决方案是搭建一个消息服务集群。具体的技术实现可以是主从架构,也可以是分布式架构。即使一个消息队列服务机挂了,也不影响消息队列不能提供服务!也有许多常用的解决方案来增加系统的复杂性。例如,接收方收到消息后,可以先将消息写入数据库。即使没有正确处理,也可以手动处理,或者消息消费失败,消息会重新入队等待下一次消费等。3.常用消息队列与目前主流的MQ产品相比,有ActiveMQ、RabbitMQ、RocketMQ、Kafka,而且都是开源的,而且各有特色。总结如下1.ActiveMQ社区比较成熟,但是相对于现在的情况,ActiveMQ的性能比较差,版本迭代很慢,所以不推荐使用。2、RabbitMQ在吞吐量上略逊于Kafka和RocketMQ,但由于是基于erlang开发的,并发性强,性能优异,延迟低,达到微秒级。但也因为RabbitMQ是基于erlang开发的,国内很少有公司有实力做erlang源码层面的研究和定制。如果业务场景对并发量要求不高(十万级、百万级),那么这四种消息队列中,首选RabbitMQ。大数据领域的实时计算、日志采集等场景,用Kafka是行业标准,绝对没问题,社区很活跃,永远不会黄,更何况几乎是一个全世界该领域的事实规范。3、RocketMQ是阿里出品的,Java是一个开源项目,我们可以直接阅读源码,然后定制自己公司的MQ,而且RocketMQ有阿里巴巴实际业务场景的实战检验。RocketMQ社区比较活跃,不过还好,文档也比较简单。还有就是阿里引进的技术。如果放弃这项技术,您必须应对社区变得过时的风险。如果你们公司有技术实力,我觉得用RocketMQ是非常不错的。4、Kafka的特点其实很明显,就是只提供了较少的核心功能,但是提供了超高的吞吐量,ms级的延迟,极高的可用性和可靠性,分布可以任意扩展。同时,Kafka最好支持少量的topic,以保证其超高的吞吐量。Kafka唯一的缺点就是有可能重复消费消息,这对数据的准确性会有非常轻微的影响。在大数据和日志采集领域,这种轻微的影响可以忽略不计。Kafka天生适合大数据实时计算和日志采集。4.小结本文主要对消息队列的历史和基础知识进行梳理和介绍。如有不妥之处,请大家批评指正!五、参考资料一、Java工程师面试突击季1-Mr.消息中间件发展史3、Java指南-消息队列