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

294 阅读5分钟

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

一、重点内容

  1. 消息队列的基本概念

  2. 三大消息队列

  • Kafka
  • BMQ(本文未给出)
  • RocketMQ(本文未给出)

二、详细知识点介绍

1 消息队列的基本概念

消息队列(Message Queue,MQ),指保存消息的一个队列,本质是个队列,但是支持高吞吐、高并发,并且高可用。消息队列是一个生产者-消费者模型,可以有效解决应用解耦、异步消息、流量削峰等问题。

2022-05-31-14-18-00-image.png

2 Kafka

Kafka是一个分布式的、分区的、多副本的消息队列,在高吞吐场景下发挥出色。

2.1 Kafka的基本使用

首先需要创建一个Kafka集群,然后在该集群中创建一个Topic,并且设置好分片数量。接着编写生产者逻辑,初始化一个生产者,再编写消费者逻辑,初始化一个消费者。

2.2 Kafka的架构

2022-05-31-17-19-37-image.png

  • Cluster:物理集群,每个集群中可以建立多个不同的Topic
  • ZooKeeper:负责存储集群元信息,包括分区分配信息等
  • Producer:生产者,负责将业务消息发送到Topic
  • Consumer:消费者,负责消费Topic中的消息
  • ConsumerGroup:消费者组,不同组Consumer消费进度互不干涉

2.3 Kafka的优点

为了提高Kafka的吞吐和稳定性,在设计上,有以下几个优化点:

2.3.1 Producer部分

在该部分,采用了批量发送数据压缩的方法来提高Kafka的吞吐量。

批量发送就是指生产者将一批消息打包成一个Batch进行发送,这样一次就可以发送多个消息,可以有效减少IO次数,增强发送能力。

但是批量发送会导致一个问题——如果服务器的网络带宽不高,例如带宽只有1MB,如果一个Batch的消息量很大,带宽会不够。由此,提出了数据压缩,通过一些压缩算法,减少要发送的Batch大小。目前Kafka支持的压缩算法有Snappy、Gzip、LZ4、ZSTD。

2.3.2 Broker部分

在该部分,采用了顺序写消息索引以及零拷贝的方法来提高性能。

考虑到存储磁盘的结构特性和磁头定位方式,Kafka采用了顺序写的方式来记录消息文件,即始终在文件末尾进行添加,不会进行中间插入的操作。

Consumer发送FetchRequest请求消息数据,Broker会将指定位置的消息发送给ConsumerKafka在记录消息文件时,同时还创建了偏移量索引文件和时间戳索引文件。有了这两个索引文件,Kafka就可以使用二分法的方式快速定位要请求的消息位置。

零拷贝的方式在很多优秀的高性能框架中都有应用,其思想就在于有效减少了数据从磁盘到NIC Buffer的拷贝次数。传统数据拷贝方式中要将数据从磁盘读取到NIC Buffer,需要先将磁盘中数据拷贝到内核态的Read Buffer,再拷贝到用户态的Application Buffer,再拷贝到内核态Socket Buffer,最后到NIC Buffer,一共经历了四次拷贝。

2022-05-31-19-34-54-image.png

而采用零拷贝技术后,可以直接将数据从Read Buffer拷贝至NIC Buffer,减少了三次拷贝,效率大大提高。

2022-05-31-19-36-17-image.png

2.3.3 Consumer部分

对于一个Consumer Group,多个分片可以并发的消费,以此提高消费的效率。但需要解决 ConsumerPartition的分配问题,即对于每一个Partition来说,该由哪一个Consumer来消费。除了手动分配以外,Kafka采用了Rebalance的方法提供自动分配。简单来说,在Broker集群中,对于不同的Consumer Group来讲,都会选取一台Broker当作Coordinator,而它的作用就是帮助Consumer Group进行分片的分配。采取该方式后,即使Consumer Group中有发生宕机,或者有新的Consumer加入,Kafka会自动进行重新分配,达到稳定的消费状态。

2.4 Kafka存在的问题

尽管上述内容例举了Kafka的诸多优点和性能优化方式,但是由于其本身的结构性质和相关策略,还是存在不少的问题。例如:由于数据复制的问题,运维成本高;对于负载不均衡的场景,解决方案会很复杂;没有自己的缓存,完全依赖Page Cache,灵活性不高;ControllerCoordinator以及Broker在同一进程中,大量的IO会导致性能下降,甚至影响到整个集群。

为了解决这些问题,字节跳动自研的ByteMQ (BMQ)采取了一定的策略进行优化。

未完待续...

三、课后个人总结

这节课,不仅对消息队列的概念进行了详细的介绍,而且还选取了市面上主流的几款消息队列产品进行分析,透彻讲述了它们的原理和工作方式。涉及了不少底层架构知识,还需要慢慢消化。这篇笔记分析了Kafka这一消息队列,在下一篇笔记中,我将继续对余下的两个消息队列BMQRocketMQ进行讲述。

四、引用参考