消息队列选型手册

前言

消息队列中间件重要吗?面试必问问题之一,你说重不重要。我有时会问同事,为啥你用 RabbitMQ,不用 Kafka,或者 RocketMQ 呢?

他给我的回答:“因为公司用的就是这个,大家都这么用”,如果你去面试,直接就被 Pass,今天这篇文章,告诉你如何回答。

这篇文章,我重点突出消息队列选型,弱化每种队列内部的实现细节,精华提炼,可读性更强!

常用的消息队列主要这 4 种,分别为 Kafka、RabbitMQ、RocketMQ 和 ActiveMQ,主要介绍前三,不 BB,上思维导图!

消息队列基础

| 什么是消息队列?

消息队列是在消息的传输过程中保存消息的容器,用于接收消息并以文件的方式存储。

一个消息队列可以被一个也可以被多个消费者消费,包含以下 3 元素:

  • Producer:消息生产者,负责产生和发送消息到 Broker。

  • Broker:消息处理中心,负责消息存储、确认、重试等,一般其中会包含多个 Queue。

  • Consumer:消息消费者,负责从 Broker 中获取消息,并进行相应处理。

| 消息队列模式

点对点模式:多个生产者可以向同一个消息队列发送消息,一个具体的消息只能由一个消费者消费。

发布/订阅模式:单个消息可以被多个订阅者并发的获取和处理。

| 消息队列应用场景

如下:

  • 应用解耦:消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节。

  • 异步处理:消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息。

  • 流量削锋:当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的”载体”,在下游有能力处理的时候,再进行分发与处理。

  • 日志处理:日志处理是指将消息队列用在日志处理中,比如 Kafka 的应用,解决大量日志传输的问题。

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

  • 消息广播:如果没有消息队列,每当一个新的业务方接入,我们都要接入一次新接口。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。

常用消息队列

由于官方社区现在对 ActiveMQ 5.x 维护越来越少,较少在大规模吞吐的场景中使用,所以我们主要讲解 Kafka、RabbitMQ 和 RocketMQ。

| Kafka

Apache Kafka 最初由 LinkedIn 公司基于独特的设计实现为一个分布式的提交日志系统,之后成为 Apache 项目的一部分,号称大数据的杀手锏,在数据采集、传输、存储的过程中发挥着举足轻重的作用。

它是一个分布式的,支持多分区、多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统。

①重要概念

如下:

  • 主题(Topic):消息的种类称为主题,可以说一个主题代表了一类消息,相当于是对消息进行分类,主题就像是数据库中的表。

  • 分区(partition):主题可以被分为若干个分区,同一个主题中的分区可以不在一个机器上,有可能会部署在多个机器上,由此来实现 Kafka 的伸缩性。

  • 批次:为了提高效率, 消息会分批次写入 Kafka,批次就代指的是一组消息。

  • 消费者群组(Consumer Group):消费者群组指的就是由一个或多个消费者组成的群体。

  • Broker:一个独立的 Kafka 服务器就被称为 broker,broker 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。

  • Broker 集群:broker 集群由一个或多个 broker 组成。

  • 重平衡(Rebalance):消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。

②Kafka 架构

一个典型的 Kafka 集群中包含 Producer、broker、Consumer Group、Zookeeper 集群。

Kafka 通过 Zookeeper 管理集群配置,选举 leader,以及在 Consumer Group 发生变化时进行 rebalance。

Producer 使用 push 模式将消息发布到 broker,Consumer 使用 pull 模式从 broker 订阅并消费消息。

③Kafka 工作原理

消息经过序列化后,通过不同的分区策略,找到对应的分区。

相同主题和分区的消息,会被存放在同一个批次里,然后由一个独立的线程负责把它们发到 Kafka Broker 上。

分区的策略包括顺序轮询、随机轮询和 key hash 这 3 种方式,那什么是分区呢?

分区是 Kafka 读写数据的最小粒度,比如主题 A 有 15 条消息,有 5 个分区,如果采用顺序轮询的方式,15 条消息会顺序分配给这 5 个分区,后续消费的时候,也是按照分区粒度消费。

由于分区可以部署在多个不同的机器上,所以可以通过分区实现 Kafka 的伸缩性,比如主题 A 的 5 个分区,分别部署在 5 台机器上,如果下线一台,分区就变为 4。

Kafka 消费是通过消费群组完成,同一个消费者群组,一个消费者可以消费多个分区,但是一个分区,只能被一个消费者消费。

如果消费者增加,会触发 Rebalance,也就是分区和消费者需要重新配对。

不同的消费群组互不干涉,比如下图的 2 个消费群组,可以分别消费这 4 个分区的消息,互不影响。

| RocketMQ

RocketMQ 是阿里开源的消息中间件,它是纯 Java 开发,具有高性能、高可靠、高实时、适合大规模分布式系统应用的特点。

RocketMQ 思路起源于 Kafka,但并不是 Kafka 的一个 Copy,它对消息的可靠传输及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binlog 分发等场景。

①重要概念

如下:

  • Name 服务器(NameServer):充当注册中心,类似 Kafka 中的 Zookeeper。

  • Broker:一个独立的 RocketMQ 服务器就被称为 broker,broker 接收来自生产者的消息,为消息设置偏移量。

  • 主题(Topic):消息的第一级类型,一条消息必须有一个 Topic。

  • 子主题(Tag):消息的第二级类型,同一业务模块不同目的的消息就可以用相同 Topic 和不同的 Tag 来标识。

  • 分组(Group):一个组可以订阅多个 Topic,包括生产者组(Producer Group)和消费者组(Consumer Group)。

  • 队列(Queue):可以类比 Kafka 的分区 Partition。

②RocketMQ 工作原理

RockerMQ 中的消息模型就是按照主题模型所实现的,包括 Producer Group、Topic、Consumer Group 三个角色。

为了提高并发能力,一个 Topic 包含多个 Queue,生产者组根据主题将消息放入对应的 Topic,下图是采用轮询的方式找到里面的 Queue。

RockerMQ 中的消费群组和 Queue,可以类比 Kafka 中的消费群组和 Partition:不同的消费者组互不干扰,一个 Queue 只能被一个消费者消费,一个消费者可以消费多个 Queue。

消费 Queue 的过程中,通过偏移量记录消费的位置。

③RocketMQ 架构

RocketMQ 技术架构中有四大角色 NameServer、Broker、Producer 和 Consumer,下面主要介绍 Broker。

Broker 用于存放 Queue,一个 Broker 可以配置多个 Topic,一个 Topic 中存在多个 Queue。

如果某个 Topic 消息量很大,应该给它多配置几个 Queue,并且尽量多分布在不同 broker 上,以减轻某个 broker 的压力。

Topic 消息量都比较均匀的情况下,如果某个 broker 上的队列越多,则该 broker 压力越大。

简单提一下,Broker 通过集群部署,并且提供了 master/slave 的结构,slave 定时从 master 同步数据(同步刷盘或者异步刷盘),如果 master 宕机,则 slave 提供消费服务,但是不能写入消息。

看到这里,大家应该可以发现,RocketMQ 的设计和 Kafka 真的很像!

| RabbitMQ

RabbitMQ 2007 年发布,是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。

AMQP 的主要特征是面向消息、队列、路由、可靠性、安全。AMQP 协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

①重要概念

如下:

  • 信道(Channel):消息读写等操作在信道中进行,客户端可以建立多个信道,每个信道代表一个会话任务。

  • 交换器(Exchange):接收消息,按照路由规则将消息路由到一个或者多个队列;如果路由不到,或者返回给生产者,或者直接丢弃。

  • 路由键(RoutingKey):生产者将消息发送给交换器的时候,会发送一个 RoutingKey,用来指定路由规则,这样交换器就知道把消息发送到哪个队列。

  • 绑定(Binding):交换器和消息队列之间的虚拟连接,绑定中可以包含一个或者多个 RoutingKey。

②RabbitMQ 工作原理

AMQP 协议模型由三部分组成:生产者、消费者和服务端。

执行流程如下:

  • 生产者是连接到 Server,建立一个连接,开启一个信道。

  • 生产者声明交换器和队列,设置相关属性,并通过路由键将交换器和队列进行绑定。

  • 消费者也需要进行建立连接,开启信道等操作,便于接收消息。

  • 生产者发送消息,发送到服务端中的虚拟主机。

  • 虚拟主机中的交换器根据路由键选择路由规则,发送到不同的消息队列中。

  • 订阅了消息队列的消费者就可以获取到消息,进行消费。

③常用交换器

RabbitMQ 常用的交换器类型有 direct、topic、fanout、headers 四种。具体的使用方法,可以参考官网:RabbitMQ Tutorials — RabbitMQ

https://www.rabbitmq.com/getstarted.html

消息队列对比&选型

| 消息队列对比

①Kafka

优点如下:

  • 高吞吐、低延迟:Kafka 最大的特点就是收发消息非常快,Kafka 每秒可以处理几十万条消息,它的最低延迟只有几毫秒。

  • 高伸缩性:每个主题(topic)包含多个分区(partition),主题中的分区可以分布在不同的主机(broker)中。

  • 高稳定性:Kafka 是分布式的,一个数据多个副本,某个节点宕机,Kafka 集群能够正常工作。

  • 持久性、可靠性、可回溯:Kafka 能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,支持消息回溯。

  • 消息有序:通过控制能够保证所有消息被消费且仅被消费一次。

  • 有优秀的第三方 Kafka Web 管理界面 Kafka-Manager,在日志领域比较成熟,被多家公司和多个开源项目使用。

缺点如下:

  • Kafka 单机超过 64 个队列/分区,Load 会发生明显的飙高现象,队列越多,load 越高,发送消息响应时间变长。

  • 不支持消息路由,不支持延迟发送,不支持消息重试。

  • 社区更新较慢。

②RocketMQ

优点如下:

  • 高吞吐:借鉴 Kafka 的设计,单一队列百万消息的堆积能力。

  • 高伸缩性:灵活的分布式横向扩展部署架构,整体架构其实和 Kafka 很像。

  • 高容错性:通过 ACK 机制,保证消息一定能正常消费。

  • 持久化、可回溯:消息可以持久化到磁盘中,支持消息回溯。

  • 消息有序:在一个队列中可靠的先进先出(FIFO)和严格的顺序传递。

  • 支持发布/订阅和点对点消息模型,支持拉、推两种消息模式。

  • 提供 docker 镜像用于隔离测试和云集群部署,提供配置、指标和监控等功能丰富的 Dashboard。

缺点如下:

  • 不支持消息路由,支持的客户端语言不多,目前是 java 及 c++,其中 c++ 不成熟。

  • 部分支持消息有序:需要将同一类的消息 hash 到同一个队列 Queue 中,才能支持消息的顺序,如果同一类消息散落到不同的 Queue中,就不能支持消息的顺序。

  • 社区活跃度一般。

③RabbitMQ

优点如下:

  • 支持几乎所有最受欢迎的编程语言:Java,C,C ++,C#,Ruby,Perl,Python,PHP 等等。

  • 支持消息路由:RabbitMQ 可以通过不同的交换器支持不同种类的消息路由。

  • 消息时序:通过延时队列,可以指定消息的延时时间,过期时间 TTL 等。

  • 支持容错处理:通过交付重试和死信交换器(DLX)来处理消息处理故障。

  • 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker。

  • 社区活跃度高。

缺点如下:

  • Erlang 开发,很难去看懂源码,不利于做二次开发和维护,基本只能依赖于开源社区的快速维护和修复 bug。

  • RabbitMQ 吞吐量会低一些,这是因为他做的实现机制比较重。

  • 不支持消息有序、持久化不好、不支持消息回溯、伸缩性一般。

| 消息队列选型

Kafka:追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务,大型公司建议可以选用,如果有日志采集功能,肯定是首选 Kafka。

RocketMQ:天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。

RocketMQ 在稳定性上可能更值得信赖,这些业务场景在阿里双 11 已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择 RocketMQ。

RabbitMQ:结合 erlang 语言本身的并发优势,性能较好,社区活跃度也比较高,但是不利于做二次开发和维护,不过 RabbitMQ 的社区十分活跃,可以解决开发过程中遇到的 bug。如果你的数据量没有那么大,小公司优先选择功能比较完备的 RabbitMQ。

ActiveMQ:官方社区现在对 ActiveMQ 5.x 维护越来越少,较少在大规模吞吐的场景中使用。

综合上面的材料得出以下两点:


(1)中小型软件公司 建议选RabbitMQ

一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便。正所谓,成也萧何,败也萧何!他的弊端也在这里,虽然RabbitMQ是开源的,然而国内有几个能定制化开发erlang的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要。不考虑rocketmq和kafka的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。不考虑rocketmq的原因是,rocketmq是阿里出品,如果阿里放弃维护rocketmq,中小型公司一般抽不出人来进行rocketmq的定制化开发,因此不推荐。


(2)大型软件公司 根据具体使用在RocketMq和Kafka之间二选一

大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对rocketMQ,大型软件公司也可以抽出人手对rocketMQ进行定制化开发,毕竟国内有能力改JAVA源码的人,还是相当多的。至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。具体该选哪个,看使用场景。 

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

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

相关文章

Jenkins 持续集成国产嵌入式操作系统 RT-Thread 的CI

我们直接在Jenkins的镜像基础上进行集成RT-Thread 的编译环境, 这样直接使用Shell 命令 最直接了当, 通过 第三方docker等插件, 尝试了计重方案, 没有找到理想中的感觉, 如果其他人有想法可以告知一二。 我们有现成的镜…

codevs原创抄袭题 5960 信使

题目描述 Description•战争时期,前线有n个哨所,每个哨所可能会与其他若干个哨所之间有通信联系。信使负责在哨所之间传递信息,当然,这是要花费一定时间的(以天为单位)。指挥部设在第一个哨所。当指挥部下达…

VC解析XML--使用CMarkup类解析XML

经过今天尝试MFC解析XML串,也算有了不少收获,总结一下。 我是使用的CMarkup类对XML进行操作。 CMarkup好象都是先从一个xml文件里面把内容读出来,再进行解析,搞得我恨不得要把我的CString写到xml文件里面…

MongoDB精华总结

概述 MongoDB是属于文档型的NoSQL数据库,也就是文档数据库。文档数据库区别于传统的其它数据库,它是用来管理文档。在传统的数据库中,信息被分割成离散的数据段,而在文档数据库中,文档是处理信息的基本单位&#xff0c…

认清性能问题

本文翻译自 Thinking Clearly About Performance 这是我三年前读到的一篇关于性能问题的好文,读完后还觉不过瘾,怕理解的不够遂又翻译了一遍,这也是当年我的第一次翻译。 这几年来每次碰到性能问题,我都会想起这篇文章&#xff0c…

字节也开始缩招了...

阅读本文大概需要6分钟。最近和一个字节技术总监聊天,得知他们公司居然也开始缩招了。这真让人感到意外,毕竟头条这些年是以极速扩张而闻名。搜了搜新闻还真是,这也意味着互联网行业最后一个坚挺的大户也在开源节流了。最近互联网行业的情况真…

实现打字效果

摘自一个表白网站的效果。 方法: substr() 可在字符串中抽取从 第一个参数表示从指定的下标,第二个参数表示抽取指定数目的字符。 indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置,两个参数,第一位指定的字符串&…

php优化-》常用到的部分优化

1.循环内部尽可能不要声明变量; 2.在可以用PHP内部字符串操作函数的情况下,尽量不要用正则表达式; 3.foreach效率更高,尽量用foreach代替while和for循环; 4.用单引号替代双引号引用字符串; 5.尽量的少进行文…

简述:分布式CAP理论和BASE理论

目录 一、什么是CAP? Consistency (一致性): Availability (可用性): Partition Tolerance (分区容错性): 二、取舍策略 三、Base理论 1、基本可用 2、软状态 3、最终一致性 四、常见产品 Ereka Zookeeper 五、总结 一、什么是CAP&#xf…

WinForm(四)一种实现登录的方式

首先声明,这只是一种登录方式,并不是最好的方式,用这个例子为了说明登录窗体和Application的关系。在登录前,定义了用户实体,然后是一个通用的类,存放进程中当前登录的用户,所以CurrentUser是静…

Java多线程4:synchronized锁机制

脏读 一个常见的概念。在多线程中,难免会出现在多个线程中对同一个对象的实例变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实是被更改过的。 按照正常来看应该打印&quo…

mysql 日期时间类型 自动转型 及 运算

日期时间类型自动转型 -- now()、字符串、数字转datetime类型 create table t(dt datetime);insert into t values(now());insert into t values(2007-9-3 12:10:10);insert into t values(2007/9/3 121010);insert into t values(2007#9#3 121010);insert into t values(20079…

.NET Community Toolkit 8.0.0 版本发布

.NET 社区工具包(.NET Community Toolkit )现已发布 8.0.0 版!.NET 社区工具包是一组适用于所有 .NET 开发人员,且与任何特定 UI 平台无关的帮助程序和 API。该工具包由 Microsoft 维护和发布,是 .NET 基金会的一部分&…

SpringData JPA、Hibernate、Mybatis三者的区别

目录 1.ORM 考虑 SpringData JPA Hibernate MyBatis 2.业务查询的区别 Spring Data JPA Hibernate Mybatis 3.可拓展性 Spring Data JPA Hibernate Mybatis 4.对缓存 Spring Data JPA Hibernate Mybatis 5.难度性 Spring Data JPA Hibernate Mybatis 总述…

1、内存

程序为什么需要内存 程序运行的目的:程序运行是为了得到一定的结果,程序运行其实是在做一系列的数据计算,所以:程序代码数据;程序运行的目的不外乎2个:过程、结果; 用函数来类比:…

Map 遍历取值及jstl的取值

Map 遍历取值及jstl的取值 学习了&#xff1a;http://blog.csdn.net/yanjiaye520/article/details/17354239 1、Java map的便利取值 Java代码 收藏代码 Map<String,String> map new HashMap<String,String>(); map.put("key1", "value1");…

基于CAP组件实现补偿事务与幂等性保障

【.NET Core】| 总结/Edison Zhou1补偿事务和幂等性在微服务架构下&#xff0c;我们会采用异步通信来对各个微服务进行解耦&#xff0c;从而我们会用到消息中间件来传递各个消息。 补偿事务某些情况下&#xff0c;消费者需要返回值以告诉发布者执行结果&#xff0c;以便于发布者…

Docker与k8s

前言 随着k8s 作为容器编排解决方案变得越来越流行&#xff0c;有些人开始拿 Docker 和 k8s进行对比&#xff0c;不禁问道&#xff1a;Docker 不香吗&#xff1f; k8s 是kubernets的缩写&#xff0c;’8‘代表中间的八个字符。 其实 Docker 和 k8s 并非直接的竞争对手&#xff…

Linux下启动tomcat报java.lang.OutOfMemoryError: PermGen space

2019独角兽企业重金招聘Python工程师标准>>> 一、错误信息 java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav…

Redis安装[Windows]

一. redis下载地址: https://github.com/ServiceStack/redis-windows/tree/master/downloads 根据需要的下载对应版本*.zip即可.(我这里是win7x64) 二.使用 1. 下载之后解压到你相应的目录下: 1 文件介绍&#xff1a; 2 redis-benchmark.exe #基准测试 3 redis-check-aof.e…