消息队列详解:ActiveMQ、RocketMQ、RabbitMQ、Kafka

2020-05-09 09:22:39 82211

目录

1.消息队列/消息中间件介绍

1.1 消息中间件是什么

1.1.1 消息中间件的组成

1.2 消息中间件能干什么

1.3 消息中间件怎么用

1.3.1 消息传递模式

1.3.2 消息中间件种类

1.3.3 各类消息中间件的具体使用操作

2.各类MQ实现原理

3.总结


1.消息队列/消息中间件介绍

对于消息中间件(消息队列)想必做IT行业的技术人员,一般都略有耳闻。但是对于它的具体含义或是使用原理,也许就是层次不齐了。今天,就带着学习和复习的心态,一起捋一捋消息中间件的那些个事儿。

首先,我们先来一击灵魂三拷问:消息中间件是什么?能干什么?怎么干?

1.1 消息中间件是什么

消息中间件:是利用高效可靠的消息传递机制进行异步的数据传输,并基于数据通信进行分布式系统的集成。通过提供消息队列模型和消息传递机制,可以在分布式环境下扩展进程间的通信。

我个人理解:消息中间件就是一个具有接受和发布消息集于一体的消息器,而这个消息器还具有保证消息有序性,分发,数据存储等多种特性。

1.1.1 消息中间件的组成

Broker:消息服务器,作为server提供消息核心服务

Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。

Producer:消息生产者,业务的发起方,负责生产消息传输给broker,

Consumer:消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理

Topic:主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播

Queue:队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收

Message:消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输

1.2 消息中间件能干什么

  • 数据的异步通信,开发人员不需要考虑网络协议和远程调用的问题
  • 系统业务解耦。分布系统之间,不必直接强依赖
  • 消息数据入队出队,流量削峰
  • 跨平台跨语种的消息通讯
  • 可做缓冲等

1.3 消息中间件怎么用

1.3.1 消息传递模式

消息中间件一般分为两种消息传递模式:点对点模式 | 发布/订阅模式

点对点模式:消息生产者将消息发送到队列中,消息消费者从队列中接收消息。消息可以在队列中进行异步传输。

说明:
消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。
消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

发布/订阅模式:发布订阅模式是通过一个内容节点来发布和订阅消息,这个内容节点称为主题(topic),消息发布者将消息发布到某个主题,消息订阅者订阅这个主题的消息,主题相当于一个中介。主题是的消息的发布与订阅相互独立,不需要进行基础即可保证消息的传递,发布/订阅模式在消息的一对多广播是采用。

说明:
消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。

两种模式的区别:

  • queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。
  • topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者都能得到一个消息的拷贝。

1.3.2 消息中间件种类

①RocketMQ

阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,目前主要多用于订单交易系统。

具有以下特点:

  • 能够保证严格的消息顺序
  • 提供针对消息的过滤功能
  • 提供丰富的消息拉取模式
  • 高效的订阅者水平扩展能力
  • 实时的消息订阅机制
  • 亿级消息堆积能力

优点

  1. 单机支持1万以上持久化队列;
  2. RocketMQ的所有消息都是持久化的,先写入系统PAGECACHE,然后刷盘,可以保证内存与磁盘都有一份数据,而访问时,直接从内存读取。
  3. 模型简单,接口易用(JMS的接口很多场合并不太实用);
  4. 性能非常好,可以允许大量堆积消息在Broker中;
  5. 支持多种消费模式,包括集群消费、广播消费等;
  6. 各个环节分布式扩展设计,支持主从和高可用;
  7. 开发度较活跃,版本更新很快。

缺点

  1. 支持的 客户端语言不多,目前是Java及C++,其中C++还不成熟;
  2. RocketMQ社区关注度及成熟度也不及rabbitMQ等;
  3. 没有Web管理界面,提供了一个 CLI (命令行界面) 管理工具带来查询、管理和诊断各种问题;
  4. 没有在MQ核心里实现JMS等接口;

②RabbitMQ

使用Erlang编写的一个开源的消息队列,本身支持很多的协议:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进行企业级的ESB整合。

优点

  1. 由于Erlang语言的特性,消息队列性能较好,支持高并发;
  2. 健壮、稳定、易用、跨平台、支持多种语言、文档齐全;
  3. 有消息确认机制和持久化机制,可靠性高;
  4. 高度可定制的路由;
  5. 管理界面较丰富,在互联网公司也有较大规模的应用,社区活跃度高。

缺点

  1. 尽管结合 Erlang 语言本身的并发优势,性能较好,但是不利于做二次开发和维护;
  2. 实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点 增加了延迟,消息封装后也比较大;需要学习比较复杂的接口和协议,学习和维护成本较高。

③ActiveMQ

Apache下的一个子项目。使用Java完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,少量代码就可以高效地实现高级应用场景。可插拔的传输协议支持,比如:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支持常用的多种语言客户端 C++、Java、.Net,、Python、 Php、 Ruby等。

优点

  1. 跨平台(JAVA编写与平台无关,ActiveMQ几乎可以运行在任何的JVM上);
  2. 可以用JDBC:可以将数据持久化到数据库。虽然使用JDBC会降低ActiveMQ的性能,但是数据库一直都是开发人员最熟悉的存储介质;
  3. 支持JMS规范:支持JMS规范提供的统一接口;
  4. 支持自动重连和错误重试机制;
  5. 有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权;
  6. 监控完善:拥有完善的监控,包括WebConsole,JMX,Shell命令行,Jolokia的RESTful API;
  7. 界面友善:提供的WebConsole可以满足大部分情况,还有很多第三方的组件可以使用,比如hawtio;

缺点

  1. 社区活跃度不及RabbitMQ高;
  2. 根据其他用户反馈,会出莫名其妙的问题,会丢失消息;
  3. 目前重心放到activemq6.0产品Apollo,对5.x的维护较少;
  4. 不适合用于上千个队列的应用场景;

④Kafka

Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,具有以下特性:

  • 快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;
  • 高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;
  • 高堆积:支持topic下消费者较长时间离线,消息堆积量大;
  • 完全的分布式系统:Broker、Producer、Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;
  • 支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。

优点

  1. 客户端语言丰富:支持Java、.Net、PHP、Ruby、Python、Go等多种语言;
  2. 高性能:单机写入TPS约在100万条/秒,消息大小10个字节;
  3. 提供完全分布式架构,并有replica机制,拥有较高的可用性和可靠性,理论上支持消息无限堆积;
  4. 支持批量操作;
  5. 消费者采用Pull方式获取消息。消息有序,通过控制能够保证所有消息被消费且仅被消费一次;
  6. 有优秀的第三方KafkaWeb管理界面Kafka-Manager;
  7. 在日志领域比较成熟,被多家公司和多个开源项目使用。

缺点

  1. Kafka单机超过64个队列/分区时,Load时会发生明显的飙高现象。队列越多,负载越高,发送消息响应时间变长;
  2. 使用短轮询方式,实时性取决于轮询间隔时间;
  3. 消费失败不支持重试;
  4. 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;
  5. 社区更新较慢。

⑤Redis

使用C语言开发的一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

下面对主流的四大消息中间件做一个对比图展示:

适用场景

从公司基础建设力量角度

  1. 中小型软件公司,建议选RabbitMQ,一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便。他的弊端也在这里,虽然RabbitMQ是开源的,然而国内有几个能定制化开发erlang的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要。不考虑RocketMQ和kafka的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。不考虑RocketMQ的原因是,RocketMQ是阿里出品,如果阿里放弃维护RocketMQ,中小型公司一般抽不出人来进行RocketMQ的定制化开发,因此不推荐。
  2. 大型软件公司,根据具体使用在RocketMQ和kafka之间二选一。一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对RocketMQ,大型软件公司也可以抽出人手对RocketMQ进行定制化开发,毕竟国内有能力改JAVA源码的人,还是相当多的。至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。

从业务场景角度出发

  1. RocketMQ定位于非日志的可靠消息传输(日志场景也OK),目前RocketMQ在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。
  2. Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache定级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
  3. RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

1.3.3 各类消息中间件的具体使用操作

activeMQ使用参考:https://blog.csdn.net/liuyuanq123/article/details/79109218

rabbitMQ使用参考:https://www.cnblogs.com/vipstone/p/9275256.html

rocketMQ使用参考:https://blog.csdn.net/zhangcongyi420/article/details/82593982

kafka使用参考:https://blog.csdn.net/tangdong3415/article/details/53432166

2.各类MQ实现原理

本篇主要针对各类MQ之间的对比说明,所以对于具体操作和各自原理实现,本篇就不一一列举了

activeMQ原理篇参考:https://www.jianshu.com/p/3a29b032827a

rabbitMQ原理篇参考:https://blog.csdn.net/maihilton/article/details/80928661

rocketMQ原理参考:https://blog.csdn.net/qq_27641935/article/details/86539980

kafka原理篇参考:https://blog.csdn.net/lp284558195/article/details/80297208

3.总结

个人认为,虽然消息中间件的种类很多,远不止我上面介绍的这几种。但上面分享的,都可谓目前行业中的主流。其实并不用每一种都会用且十分了解,但精通一种主流的消息中间件是必须的。所谓通而不精,其间也都是大同小异,所以精通一种,也就基本可达到触类旁通的效果。

参考链接:

https://blog.csdn.net/sinat_41523355/article/details/100515673

https://blog.csdn.net/yexiaomodemo/article/details/80444732

https://www.cnblogs.com/lifeibai/p/9167701.html

https://blog.csdn.net/wqc19920906/article/details/82193316

https://my.oschina.net/blogByRzc/blog/3012251


转载:https://blog.csdn.net/yy339452689/article/details/103968481

随缘而来,乘风而去,山高海阔,自有我风采!
所属分类:Java