一、消息队列基础
1.1 什么是消息队列
消息队列是在消息的传输过程中保存消息的容器,用于接收消息并以文件的方式存储,一个消息队列可以被一个也可以被多个消费者消费,包含以下 3 元素:
-
Producer:消息生产者,负责产生和发送消息到 Broker;
-
Broker:消息处理中心,负责消息存储、确认、重试等,一般其中会包含多个 Queue;
-
Consumer:消息消费者,负责从 Broker 中获取消息,并进行相应处理。
1.2 消息队列模式
-
点对点模式:多个生产者可以向同一个消息队列发送消息,一个具体的消息只能由一个消费者消费。
-
发布/订阅模式:单个消息可以被多个订阅者并发的获取和处理。
1.3 消息队列使用场景
-
应用解耦:消息队列减少了服务之间的耦合性,不同的服务可以通过消息队列进行通信,而不用关心彼此的实现细节。
-
异步处理:消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息。
-
流量削锋:当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的”载体”,在下游有能力处理的时候,再进行分发与处理。
-
日志处理:日志处理是指将消息队列用在日志处理中,比如 Kafka 的应用,解决大量日志传输的问题。
-
消息通讯:消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯,比如实现点对点消息队列,或者聊天室等。
-
消息广播:如果没有消息队列,每当一个新的业务方接入,我们都要接入一次新接口。有了消息队列,我们只需要关心消息是否送达了队列,至于谁希望订阅,是下游的事情,无疑极大地减少了开发和联调的工作量。
二、常见的消息队列中间件
2.1 消息队列主流产品
ActiveMQ:ActiveMQ 由 Apache 软件基金会基于 Java 语言开发的一个开源的消息代理,实现了JMS。
RabbitMQ:RabbitMQ 是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件)。RabbitMQ 服务器是用 Erlang 语言编写的,而集群和故障转移是构建在开放电信平台框架上的。所有主要的编程语言均有与代理接口通讯的客户端库。RabbitMQ 支持多种消息传递协议、传递确认等特性。
Kafka:Apache Kafka 是由 Apache 软件基金会开发的一个开源消息系统项目,由 Scala 写成。
Kafka 最初是由 LinkedIn 开发,并于 2011 年初开源。2012 年 10 月从 Apache Incubator 毕业。
该项目的目标是为处理实时数据提供一个统一、高通量、低等待的平台。Kafka 是一个分布式的、分区的、多复本的日志提交服务。它通过一种独一无二的设计提供了一个消息系统的功能。
RocketMQ:Apache RocketMQ 是一个分布式消息和流媒体平台,具有低延迟、强一致、高性能和可靠性、万亿级容量和灵活的可扩展性。它有借鉴 Kafka 的设计思想,但不是 Kafka 的拷贝。 基于JMS实现。
Pulsar:Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体,采用计算与存储分离架构设计。支持多租户、持久化存储、多机房跨区域数据复制,具有强一致性、高吞吐、低延时及高可扩展性等流数据存储特性,被看作是云原生时代实时消息流传输、存储和计算最佳解决方案。
2.2 消息队列的架构简介
2.2.1 Kafka
一个Kafka集群由多个Broker和一个ZooKeeper集群组成,Broker作为Kafka节点的服务器。同一个消息主题Topic可以由多个分区Partition组成,分区物理存储在Broker上。负载均衡考虑,同一个Topic的多个分区存储在多个不同的Broker上,为了提高可靠性,每个分区在不同的Broker会存在副本。
ZooKeeper是一个分布式开源的应用程序协调服务,可以实现统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等工作。Kafka里的ZooKeeper主要有一下几个作用:
-
Broker注册,当有Broker故障的时候能及时感知。
-
Topic注册,维护Topic各分区的个副本所在的Broker节点,以及对应leader/follower的角色。
-
Consumer注册,维护消费者组的offset以及消费者与分区的对应关系,实现负载均衡。
2.2.2 Pulsar
Pulsar有三个重要的组件,Broker、BookKeeper和ZooKeeper,Broker是无状态服务,客户端需要连接到Broker上进行消息的传递。BookKeeper与ZooKeeper是有状态服务。BookKeeper的节点叫Bookie,负责存储消息和游标,ZooKeeper存储Broker和Bookie的元数据。Pulsar以这种架构,实现存储和计算分离,Broker负责计算,Bookie负责有状态存储。
Pulsar的多层架构影响了存储数据的方式。Pulsar将Topic分区划分为分片(Segment),然后将这些分片存储在Apache BookKeeper的存储节点上,以提高性能、可伸缩性和可用性。Pulsar的分布式日志以分片为中心,借助扩展日志存储(通过Apache BookKeeper)实现,内置分层存储支持,因此分片可以均匀地分布在存储节点上。由于与任一给定Topic相关的数据都不会与特定存储节点进行捆绑,因此很容易替换存储节点或缩扩容。另外,集群中最小或最慢的节点也不会成为存储或带宽的短板。
2.2.3 RocketMQ
RocketMQ是阿里开源的消息中间件,它是一个开源的分布式消息传递和流式数据平台。总共有四大部分:NameServer,Broker,Producer,Consumer。
NameServer主要用来管理brokers以及路由信息。broker服务器启动时会注册到NameServer上,并且两者之间保持心跳监测机制,以此来保证NameServer知道broker的存活状态。而且,每一台NameServer都存有全部的broker集群信息和生产者/消费者客户端的请求信息。
Broker负责管理消息存储分发,主从数据同步,为消息建立索引,提供消息查询等能力。
2.2.4 RabbitMQ
RabbitMQ基于AMQP协议来实现,主要由Exchange和Queue两部分组成,然后通过RoutingKey关联起来,消息投递到Exchange然后通过Queue接收。
三、 各方面对比
3.1 总体对比
上图详细的展示了几种消息队列的各自功能及优缺点:
1.ActiveMQ 和 RabbitMQ 二者属于同一量级,在吞吐量上比后面三者差一个量级。
2.支持强一致性的有 RocketMQ 和 Pulsar,在对消息一致性要求比较高的场景可以采用这些产品。
3.同时 Kafka 虽然会有数据丢失的风险,但其吞吐量比较高同时社区非常活跃,在大数据的绝大部分场景里,都可以采用 Kafka。
4. Kafka、RocketMQ、Pulsar 这几款是基于磁盘存储数据的,内存加速访问。
5. ActiveMQ、RabbitMQ 采用内存存储数据,也支持数据持久化到磁盘。
3.2 功能、性能、运维对比
消息队列-功能、性能、运维对比-Kafka、Pulsar、RocketMQ、RabbitMQ
3.3 消息事务管理对比
消息队列-消息事务管理对比-Kafka、Pulsar、RocketMQ
3.4 综合选型
- ActiveMQ:官方社区现在对 ActiveMQ 5.x 维护越来越少,较少在大规模吞吐的场景中使用。
- RabbitMQ:结合 erlang 语言本身的并发优势,性能较好,社区活跃度也比较高,但是不利于做二次开发和维护,不过 RabbitMQ 的社区十分活跃,可以解决开发过程中遇到的 bug。如果你的数据量没有那么大,小公司优先选择功能比较完备的 RabbitMQ。
- RocketMQ:天生为金融互联网领域而生,对于可靠性要求很高的场景,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。RocketMQ 在稳定性上可能更值得信赖,这些业务场景在阿里双 11 已经经历了多次考验,如果你的业务有上述并发场景,建议可以选择 RocketMQ。
- Kafka:追求高吞吐量,一开始的目的就是用于日志收集和传输,适合产生大量数据的互联网服务的数据收集业务,大型公司建议可以选用,如果有日志采集、大数据处理,肯定是首选 kafka,Kafka都有比较成熟的解决方案。
- Pulsar:支持的功能比Kafka更丰富,而且跨地域容灾,多租户等功能,支持消息强一致性,若对消息可靠性、容灾要求更好,或者有高分区、延迟队列等需求的场景,可以选用Pulsar。