走近消息队列——Kafka | 青训营笔记

89 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记。

谈到消息队列,大家都知道异步、削峰、解藕,并且还要他和普通队列不同,能做到高吞吐、高并发、高可用。Kafka 作为一个最经典的消息队列中间价,将是这篇笔记的主角。

本文目录

  1. Kafka 简介及其大体架构
  2. Kafka 是如何提高吞吐量及稳定性的
    • 2.1 Producer: 批量发送、数据压缩
    • 2.2 Broker: 顺序写、消息索引、零拷贝
    • 2.3 Consumer: Rebalance
  3. Kafka 还存在什么问题

Kafka 简介及其大体架构

Kafka是由Apache软件基金会开发的一个开源流处理平台,由ScalaJava编写。该项目的目标是为处理实时数据提供一个统一、高吞吐、低延迟的平台。其持久化层本质上是一个“按照分布式事务日志架构的大规模发布/订阅消息队列”,这使它作为企业级基础设施来处理流式数据非常有价值。 ——来自维基百科

其大致架构如下靓图所示, 逻辑上: image.png 物理上: image.png

其中一些概念解释如下:

  • Topic 即逻辑上的队列,用户在使用时根据不同主题建立的不同队列
  • Partition 是 Topic 物理上的分组,一个 Topic 可以分成多个 Partition
  • Cluster 是物理集群,其中包含多个 Broker
  • Broker 是用来存储消息的,Cluster 中每一个 服务器就是一个 Broker
  • Producer 是生产者,将业务消息发送到 Topic 中
  • Consumer 是消费者,负责消费 Topic 中的消息
  • Consumer 是消费者组,不同组之间的消费无互不干涉

在使用上,一般的步骤是:

  1. 搭建 Kafka 集群
  2. 创建 Topic
  3. 编写生产者逻辑
  4. 编写消费者逻辑

另外,Kafka 中还有一些比较重要的基础概念。

Offset

Offset 指消息在 partition 内的相对位置信息,可以理解为唯一ID,在 partition 内严格递增。

image.png

Replica

每个分片(Partition)有多个 Replica,分布在不同的机器上以保证 Kafka 的高可用。其中 Leader Replica 会从 ISR 中选出。

  • Leader Replica:是对外服务的副本,其他 Follower 会来该副本上拉取最新数据以保证消息同步。
  • ISR:该集合内只允许存在与 Leader 差距不大的 Follower,当 Leader 挂掉时只允许从该集合内的 Follower 中选择新 Leader。

image.png

Kafka 是如何提高吞吐量及稳定性的

首先我们要知道一条消息是由 Producer 生产,发送给 Broker,再由 Consumer 消费。在这三个环节 Kafka 都有对应的优化机制。

Producer: 批量发送、数据压缩

对于 Producer 而言,如果一条一条发送消息,将会产生大量的 IO 消耗,因此最直接的方案就是采用批量发送,减少IO次数

而若消息量很大,可能会导致网络带宽不够用,于是 Kafka 便采用数据压缩的方式减少消息大小

image.png

Broker: 顺序写、消息索引、零拷贝

Broker 要将消息存储到磁盘中,如何做才能提高性能?

考虑到磁盘的结构,我们需要移动磁头找到对应磁道,磁盘转动,然后找到对应扇区,最后才进行写入。这过程中寻道成本比较高并且可优化,只要使用顺序写的方式就可以减少寻道带来的时间成本

在 Consumer 请求消息数据时,怎样才能尽快找到数据呢?

Kafka 会有一个偏移量索引文件,当消费者需要寻找基于某个 offset 的消息时,使用二分查找找到小与目标 offset 的最大文件,再顺序找到需要的文件。同样的,它还有一个时间戳索引文件,搜索方式也差不多,这里不再赘述。

在取出数据时,需要将数据从磁盘空间拷贝到内核空间,而这其中会涉及到多次拷贝,如图所示。

image.png

Kafka 采用零拷贝拘束,减少了这些额外的拷贝次数以提高性能。

image.png

Consumer: Rebalance

对于一个消费者组而言,同一个 Topic 下多个 Partition 如何分配给底下的消费者呢?

如果采取硬编码方式,将某些 Partition 分配给某个消费者,其他的分配给另一个消费者,当某个消费者进程挂了,那么它负责的 Partition 需要重新手动分配。又或者新加入了一个消费者,那要手动去除其他消费者负责的 Partition 来将这些任务让给新消费者。

因此可以采用 Rebalance 的方式,对于每个消费者组,在 Broker 中选取一台作为 Coordinator 帮助他们进行 Partition 的动态分配,整个 Rebalance 的方式如下图所示。

image.png

Kafka 还存在什么问题

  1. 运维成本高
  2. 对于负载不均衡的场景,解决方案复杂
  3. 没有自己的缓存,完全依赖 Page Cache
  4. Controller、Coordinator 和 Broker 在同一进程中,大量 IO 会造成其性能下降