走进消息队列(二) | 青训营笔记

460 阅读6分钟

前言:这是我参与「第三届青训营-后端场」笔记创作活动的第3篇笔记。这篇笔记记录了「走进消息队列」这一节的后半部分内容。

一、重点内容

1、消息队列的基本概念(见上一篇)

2、三大消息队列

  • Kafka(见上一篇)
  • BMQ
  • RocketMQ

二、详细知识点介绍

1 BMQ

ByteMQ(BMQ)是一个兼容Kafka协议,存算分离,云原生的消息队列。

1.1 BMQ与Kafka进行对比

2022-06-01-16-16-06-image.png

由表格可以看出,BMQ在重启、替换、扩容、缩容这些运维操作上的效率十分高,这得益于其架构的设计。实际上对于所有节点的变更操作,都仅仅只是集群元数据的变化,通常情况下都能秒级完成,而真正的数据存储在下层分布式文件存储系统中,因此才不需要考虑数据复制带来的时间成本。这与Kafka相比,是架构上的先进之处,也是云原生的体现。

1.2 BMQ的架构

2022-06-01-16-23-11-image.png

从架构图上可以看到,由于BMQ是兼容Kafka协议的,因此ProducerConsumer Group部分与Kafka是类似的。因为有着存算分离的特性,在底层也存在着一个分布式文件系统提供消息存储支持,采用的是HDFSMeta Storage System负责存储集群元信息,功能上与KafkaZooKeeper是类似的。

从消息流来看,当Producer提供数据给Proxy后,Proxy会将数据交给Broker来写入到HDFS中。而Consumer获取数据时,则是直接由ProxyHDFS中拿取。

上文中也有所提到,ProxyBroker本身并不存储数据,是无状态的,因此在节点变更时,只需要调整部分元信息,例如路由信息等即可,不用再考虑数据复制的问题。

2022-06-01-16-40-57-image.png

BMQ的文件结构上来看,得益于HDFS,数据均匀分散在不同的节点上,不会出现像Kafka一样的单分片过大导致负载不均衡的问题。

1.3 BMQ的读写流程

1.3.1 Broker-Partition 写入状态机

对于写入逻辑来说,存在状态机机制,用于保证不会出现同一个分片在两个Broker上同时启动的情况,同时也能保证一个分片的正常运行。

2022-06-01-16-46-13-image.png

1.3.2 Broker-写文件流程

2022-06-01-16-51-35-image.png

当接收到一条消息,首先通过CRC校验,查看数据是否合法。校验完成后,会先将数据存入Buffer中,通过一个异步的Writer线程将数据最终写入到底层的存储系统中。Writer线程的具体逻辑:首先会将Buffer中的数据取出来,调用底层写入逻辑,在一定的时间周期上flushflush完成后开始建立Index,也就是和Kafka类似的偏移量索引和时间戳索引用于查找消息的具体位置。Index建立完成后,会保存一次checkpoint,这表示checkpoint后的数据是可以被消费的。

1.3.3 Broker-写文件 Failover

建立一个新的文件时,会随机挑选与副本数量相当的数据节点进行写入,如果此时挑选的节点中有节点出现了问题,导致不能正常写入。解决方法也很简单,就是重新寻找正常的节点创建新的文件进行写入,保证了写入的可用性。

1.3.4 Proxy-读文件流程

2022-06-01-17-03-58-image.png

从流程图中可以看到,在Consumer发送了获取消息的请求后,并不会直接返回,而是经历一个Wait流程。这是因为如果一个Topic一直没有数据写入,那Consumer就会一直发送请求,如果数量达到一定规模,服务器会崩溃。因此,如果没有获取到指定大小的数据,等待机制降低了请求的IO次数。等待流程过后,先去缓存中寻找,找不到,再去存储系统中寻找。

1.4 BMQ的高级特性

2022-06-01-17-15-22-image.png

1.4.1 泳道

该特性主要是为了应对大型企业,在开发测试流程中存在的不便之处,例如:有多人需要测试不同测试场景时,需要排队,无法并行测试,搭建多套相同配置的Topic,成本又太高。

2022-06-01-17-27-46-image.png

泳道Topic解决了主干泳道流量隔离问题以及泳道资源重复创建问题。

1.4.2 Databus

该特性主要为了解决一下问题:1)客户端配置较为复杂;2)不支持动态配置,更改配置需要停掉服务;3)对于latency不是很敏感的业务,batch效果不佳。

2022-06-01-17-30-52-image.png

Databus组件简化了消息队列客户端复杂度,解耦业务与Topic,缓解集群压力,提高吞吐。

1.4.3 Mirror

2022-06-01-17-33-14-image.png

Mirror通过最终一致的方式,解决跨Region读写问题。

1.4.4 Index

2022-06-01-17-34-51-image.png

Index主要为了解决一些特殊查询的需求,即通过某些业务字段进行消息的查询。该组件可以直接在BMQ中将数据结构化,配置索引DDL,异步构建索引后,通过Index Query服务读出数据。

1.4.5 Parquet

Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容Hadoop生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、Impala、Drill等)。

2、RocketMQ

RocketMQ具有低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广。

2.1 RocketMQ的使用场景

针对电商业务线,其业务涉及广泛,如注册、订单、库存、物流等。同时,也会涉及许多业务峰值时刻,如秒杀活动、周年庆、定期特惠等。

2.2 RocketMQ的基本概念

2022-06-01-17-44-46-image.png

ProducerConsumerBroker这三个部分,KafkaRocketMQ是一样的,而Kafka中的Partition概念在这里叫做Consumer Queue

2022-06-01-17-48-03-image.png

2.3 RocketMQ的架构

2022-06-01-17-50-30-image.png

数据也是通过Producer发送给Broker集群,再由Consumer进行消费。Broker节点为主从式设计。NameServer为集群提供轻量级服务发现和路由。

2.4 RocketMQ的高级特性

2.4.1 事务消息

2022-06-01-17-57-07-image.png

RocketMQ提供了事务消息来保证一些需要事务的场景。例如,电商常见的下单流程。

2022-06-01-18-01-17-image.png

在该场景下,需要保证库存记录减一,订单记录+1,通知商家这几个操作作为一个事务共同执行。

2.4.2 延迟发送

2022-06-01-18-04-40-image.png

该特性能够帮助我们完成一些定时任务。

2.4.3 消息重试和死信队列

2022-06-01-18-12-13-image.png

该特性主要为了解决消息处理失败的情况。

三、课后个人总结

这节课,不仅对消息队列的概念进行了详细的介绍,而且还选取了市面上主流的几款消息队列产品进行分析,透彻讲述了它们的原理和工作方式。涉及了不少底层架构知识,还需要慢慢消化。每一款消息队列都有它的应用场景,它们自身的架构特性决定了能胜任哪一种场景。没有哪一款消息队列可以面面俱到,在今后的开发过程中,应该根据应用场景的需求,选取适合的消息队列使用。在课中,也提到了不少消息队列的高级特性。这些特性针对了特定的场景进行了优化,在基础使用中可能不会用到,但在大型企业中,确实十分重要的。希望在今后的学习工作中,能够慢慢接触,细细领悟。

四、引用参考