
前言可能你在没学消息中间件之前都已经听过很多概念了JMSAMQPActiveMQRabbitMQKafkaRocketMQ一个消息中间件怎么能搞出怎么多概念本文从历史的角度帮你理清这些MQ和协议之间的关系。什么是消息中间件消息中间件属于分布式系统中的一个子系统关注于数据的发送和接收利用高效可靠的消息传递机制对分布式系统中的其余各个子系统经进行集成消息中间件的使用场景1.异步处理非核心流程异步化提高系统响应性能原来用户注册一下可能得依次写数据库发送邮件和短信后才能提示用户注册成功现在只要写数据库写消息队列后就直接提示用户注册成功发送邮件和短信是异步处理提高了响应速度2.应用解耦系统不是强耦合消息接受者可以随意增加而不需要修改消息发送者的代码。消息发送者的成功不依赖消息接受者如果库存系统出了问题用户就不能正常下单这是不合理的。可以通过消息队列来解耦。当有新的系统如广告系统对用户的订单也感兴趣的时候只需要从消息队列中拿消息即可订单系统完全不用改变3.流量削峰当上下游系统处理能力存在差距的时候可以用消息队列进行缓冲当有秒杀业务时一下有大量请求涌入时很可能造成系统瘫痪此时可以用消息队列缓冲一下4.日志处理将消息队列用在日志处理中比如Kafka可以用来解决大量日志传输的问题5.消息通讯消息队列一般都内置了高效的通信机制因此也可以用于单纯的消息通讯比如实现点对点消息队列或者聊天室等消息中间件编年史初见曙光1.消息中间件其实诞生的很早在互联网应用还是一片荒芜的年代有个在美国的印度哥们Vivek Ranadive就设想了一种通用软件总线采用发布订阅的模式像主板上的总线一样供其他相应程序接入。他创办了一家公司Teknekron实现了世界上第一个消息中间件The Information Bus(TIB)各自为战2.TIB受到了企业的欢迎Teknekron的业务发展引起了当时最牛气的IT公司IBM的注意于是他们也开始研发了自己消息队列软件于是才有了后来的wesphere mq微软也陆续加入了战团。由于商业壁垒商业MQ供应商想要解决应用应用互通的问题而不是去创建标准来实现不同MQ产品间的互通或者允许应用程序更改MQ平台劫制天下3.为了打破这个壁垒同时为了能够让消息在各个消息队列平台间互融互通 JMS (Java Message Service) 应运而生 。 JMS 试图通过提供公共 Java API 的方式隐藏单独 MQ 产品供应 商提供的实际接口从而跨越了壁垒以及解决了互通问题。从技术上讲 Java 应用程序只需 针对 JMS API 编程选择合适的 MQ 驱动即可 JMS 会打理好其他部分 。 ActiveMQ 就是 JMS 的 一种实现 。 不过尝试使用单独标准化接口来胶合众多不同的接口最终会暴露出问题使得 应用程序变得更加脆弱 。 所以急需一种新的消息通信标准化方案 。一统江湖4.在 2006 年 6 月由 Cisco 、 Redhat 、iMatix 等联合制定了 AMQP 的公开标准由此 AMQP 登上了历史的舞台 。 它是应用层协议的一个开放标准以解决众多消息中间件的需求和拓扑结 构问题 。 它为面向消息的中间件设计基于此协议的客户端与消息中间件可传递消息并不受 产品、开发语言等条件的限制 。合久必分5.LinkedIn在实现消息队列的时候觉得AMQP规范并不适合自己所以Kafka并不支持AMQP协议。RocketMQ在实现上借鉴了Kakfa的思想所以也不支持AMQP协议并且你会发现在Kafka和RocketMQ中都有类似Topic和Consumer Group的概念而这些概念在AMQP协议中是不存在的消息模型如果让你设计一个消息队列你会怎么实现呢可能你立马就会想到用队列一边放一边取。这其实就是消息队列常见的一种消息模型队列模型所以一个简单的消息队列用Redis中的List就能实现。当然Redis5.0版本之后针对消息队列这种场景新增了专门设计了一个数据结构Streams。队列模型有哪些缺点呢如果将一类消息发送给不同的消费者每个消费者都要接收全量的消息此时就很不方便。因为你要将相同的消息发送到不同的队列多一个消费者就得多发一份队列。这样生产者必须知道有多少个消费者不利于解耦。那么该如何解决这个问题呢想想RabbitMQ的结构图RabbitMQ并不是直接把消息发送到队列中的而是发送到Exchange中Exchange和Queue进行关联消息由Exchange根据规则发送到对应的队列。这样生产者和消费者完成了解耦。还有哪种方式能解决这种多消费者的问题呢答对了就是发布订阅模型RocketMQ和Kafka都是基于发布订阅模型实现的RocketMQ的消息模型图如下生产者是发布者消费者是订阅者消息是主题为了提高消费的并行度一类消息会被分发到多个队列中在RocketMQ中叫Queue在Kafka中叫做Partition分区都是类似的概念。如何选择消息中间件对比维度RabbitMqKafkaRocketMq核心定位主打复杂路由微秒级低延迟分布式流处理平台主打海量日志和高吞吐金融级业务消息中间件主打高并发与业务特性开发语言ErlangScala/JavaJava单机吞吐量万级QPS百万级QPS十万级QPS时延微秒级最快毫秒级毫秒级消息堆积能力弱堆积后性能急剧下降极强磁盘顺序写堆积无性能损耗极强功能支持功能最丰富支持复杂路由、延迟/死信/优先级队列功能最简原生不支持延迟/死信/重试队列业务功能完备原生支持事务/延迟/死信/重试队列消费模式Push PullPullPush Pull适用场景微服务通信、复杂路由、低延迟业务日志收集、大数据管道、实时计算、用户行为分析电商交易、金融核心、分布式事务、需要强一致性的业务