可读性差,不想让这篇文章埋没,五一特意花了 7 重新整理一个小时。
消息队列中间件重要吗?面试中必须问的问题之一,你说重不重要。有时候我会问同事为什么用。 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 项目的一部分,
,它也是一个基于发布订阅模式的开源新闻引擎系统。
重要概念
-
:新闻的类型叫做主题,可以说一个主题代表一种新闻,相当于对新闻进行分类,主题就像数据库中的表。
-
:主题可以分为几个分区,同一主题的分区可以部署在多个机器上,而不是一台机器 kafka 的伸缩性。
-
:为提高效率, 消息会分批次写入 Kafka,批次是指一组新闻。
-
:消费者群体是指由一个或多个消费者组成的群体。
-
: 一个独立的 Kafka 被称为服务器 broker,broker 接收生产者的消息,为消息设置偏移量,并将消息提交磁盘保存。
-
:broker 一个或多个集群 broker 组成。
-
:在消费者组中的一个消费者实例被挂断后,其他消费者实例自动重新分配订阅主题分区的过程。
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 消费是通过同一消费群体完成的,
。
,比如下图的 2 消费群体可以单独消费 4 个分区的消息互不影响。
详见更多知识 原理初探之 Kafka》
RocketMQ
RocketMQ 是阿里开源的消息中间件,是纯粹的 Java 开发,
RocketMQ 思路起源于 Kafka,但并不是 Kafka 的一个 Copy,,目前广泛应用于阿里集团的交易、充值、流量计算、消息推送、日志流处理binlog 分发等场景。
重要概念
-
:充当注册中心,类似 Kafka 中的 Zookeeper。
-
: 一个独立的 RocketMQ 被称为服务器 broker,broker 接收生产者的消息,为消息设置偏移量。
-
:第一类消息,一条消息必须有 Topic。
-
:第二类消息,同一业务模块的不同目的可以使用相同的消息 Topic 和不同的 Tag 来标识。
-
:一组可以订阅多个 Topic,包括生产者组(Producer Group)和消费者组(Consumer Group)。
-
:可以类比 Kafka 的分区 Partition。
RocketMQ 工作原理
RockerMQ 根据主题模型,包括 Producer Group、Topic、Consumer Group 三个角色。
,生产者组根据主题将信息放入相应的主题 Topic,下图是采用轮询的方式找到里面的 Queue。
RockerMQ 消费 Queue,可以类 Kafka 中的消费群组和 Partition:
消费 Queue 的过程中,通过偏移量记录消费的位置。
RocketMQ 架构
RocketMQ 技术架构中有四大角色 NameServer、Broker、Producer 和 Consumer,下面主要介绍 Broker。
如果某个 Topic 消息量很大,应该给它多配置几个 Queue,并且尽量多分布在不同 broker 上,以减轻某个 broker 的压力。Topic 消息量都比较均匀的情况下,如果某个 broker 上的队列越多,则该 broker 压力越大。
简单提一下,Broker 通过集群部署,并且提供了 master/slave 的结构,slave 定时从 master 同步数据(同步刷盘或者异步刷盘),如果 master 宕机,则 slave 提供消费服务,但是不能写入消息。
看到这里,大家应该可以发现,RocketMQ 的设计和 Kafka 真的很像!
更多知识,详见 《原理初探之 RocketMQ》
RabbitMQ
RabbitMQ 2007 年发布,是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。
AMQP 的主要特征是面向消息、队列、路由、可靠性、安全。
重要概念
-
:消息读写等操作在信道中进行,客户端可以建立多个信道,每个信道代表一个会话任务。
-
:接收消息,按照路由规则将消息路由到一个或者多个队列;如果路由不到,或者返回给生产者,或者直接丢弃。
-
:生产者将消息发送给交换器的时候,会发送一个 RoutingKey,用来指定路由规则,这样交换器就知道把消息发送到哪个队列。
-
:交换器和消息队列之间的虚拟连接,绑定中可以包含一个或者多个 RoutingKey。
RabbitMQ 工作原理
AMQP 协议模型由三部分组成:生产者、消费者和服务端,执行流程如下:
-
生产者是连接到 Server,建立一个连接,开启一个信道。
-
生产者声明交换器和队列,设置相关属性,并通过路由键将交换器和队列进行绑定。
-
消费者也需要进行建立连接,开启信道等操作,便于接收消息。
-
生产者发送消息,发送到服务端中的虚拟主机。
-
虚拟主机中的交换器根据路由键选择路由规则,发送到不同的消息队列中。
-
订阅了消息队列的消费者就可以获取到消息,进行消费。
常用交换器
RabbitMQ 常用的交换器类型有 direct、topic、fanout、headers 四种,每种方法的详细介绍看这篇《入门RabbitMQ,这一篇绝对够!》。
具体的使用方法,可以参考官网:
-
官网入口:https://www.rabbitmq.com/getstarted.html
更多知识,详见 《入门RabbitMQ,这一篇绝对够!》
消息队列对比&选型
消息队列对比
Kafka
-
:Kafka 最大的特点就是收发消息非常快,Kafka 每秒可以处理几十万条消息,它的最低延迟只有几毫秒;
-
:每个主题(topic)包含多个分区(partition),主题中的分区可以分布在不同的主机(broker)中;
-
:Kafka 是分布式的,一个数据多个副本,某个节点宕机,Kafka 集群能够正常工作;
-
:Kafka 能够允许数据的持久化存储,消息被持久化到磁盘,并支持数据备份防止数据丢失,支持消息回溯;
-
消息有序:通过控制能够保证所有消息被消费且仅被消费一次;
-
有优秀的第三方 Kafka Web 管理界面 Kafka-Manager,在日志领域比较成熟,被多家公司和多个开源项目使用。
-
Kafka 单机超过 64 个队列/分区,Load 会发生明显的飙高现象,队列越多,load 越高,发送消息响应时间变长;
RocketMQ
-
:借鉴 Kafka 的设计,单一队列百万消息的堆积能力;
-
:灵活的分布式横向扩展部署架构,整体架构其实和 kafka 很像;
-
:通过ACK机制,保证消息一定能正常消费;
-
:消息可以持久化到磁盘中,支持消息回溯;
-
消息有序:在一个队列中可靠的先进先出(FIFO)和严格的顺序传递;
-
支持发布/订阅和点对点消息模型,支持拉、推两种消息模式;
-
提供 docker 镜像用于隔离测试和云集群部署,提供配置、指标和监控等功能丰富的 Dashboard。
-
不支持消息路由,;
-
部分支持消息有序:需要将同一类的消息 hash 到同一个队列 Queue 中,才能支持消息的顺序,如果同一类消息散落到不同的 Queue中,就不能支持消息的顺序。
RabbitMQ
-
:Java,C,C ++,C#,Ruby,Perl,Python,PHP等等;
-
:RabbitMQ 可以通过不同的交换器支持不同种类的消息路由;
-
:通过延时队列,可以指定消息的延时时间,过期时间TTL等;
-
支持容错处理:通过交付重试和死信交换器(DLX)来处理消息处理故障;
-
提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker;
-
,基本只能依赖于开源社区的快速维护和修复 bug;
-
,这是因为他做的实现机制比较重;
-
不支持消息有序、持久化不好、不支持消息回溯、伸缩性一般。
消息队列选型
-
Kafka:追求高吞吐量,一开始的目的就是用于日志收集和传输,,大型公司建议可以选用,
-
RocketMQ:,尤其是电商里面的订单扣款,以及业务削峰,在大量交易涌入时,后端可能无法及时处理的情况。RocketMQ 在稳定性上可能更值得信赖,这些业务场景在阿里双 11 已经经历了多次考验,
RabbitMQ:结合 erlang 语言本身的并发优势,性能较好,社区活跃度也比较高,但是不利于做二次开发和维护,不过 RabbitMQ 的社区十分活跃,可以解决开发过程中遇到的 bug。
ActiveMQ:官方社区现在对 ActiveMQ 5.x 维护越来越少,
-