大家好,我是勾叔。今天和大家聊聊kafka。为了内容路径不过于陡峭,将先和大家讲解下Kafka 基础与入门。后续再为大家进一步剖析集群容量规划和架构设计应用案例。

01Kafka 基本概念

Kafka 官方的定义:是一种高吞吐量的分布式发布/订阅消息系统。这样说起来可能不太好理解,这里简单举个例子:现在是个大数据时代,各种商业、社交、搜索、浏览都会产生大量的数据,那么如何快速收集这些数据,如何实时地分析这些数据,是一个必须要解决的问题。同时,这也形成了一个业务需求模型,即生产者生产(Produce)各种数据,消费者(Consume)消费(分析、处理)这些数据。面对这些需求,如何高效、稳定地完成数据的生产和消费呢?这就需要在生产者与消费者之间,建立一个通信的桥梁,这个桥梁就是消息系统。从微观层面来说,这种业务需求也可理解为不同系统之间如何传递消息。

02Kafka 角色术语

在介绍架构之前,先来了解下 Kafka 中的一些核心概念和各种角色。

Broker:Kafka 集群包含一个或多个服务器,每个服务器被称为 Broker。

Topic:每条发布到 Kafka 集群的消息都有一个分类,这个类别被称为 Topic(主题)。

Producer:消息的生产者,负责发布消息到 Kafka Broker。

Consumer:消息的消费者,从 Kafka Broker 拉取数据,并消费这些已发布的消息。

Partition:其是物理上的概念,每个 Topic 包含一个或多个 Partition,每个 Partition 都是一个有序的队列。Partition 中的每条消息都会被分配一个有序的 ID(称为 Offset)。

Consumer:消费者组,可以给每个 Consumer 指定消费者组,若不指定,则属于默认的 Group。

Message:消息,通信的基本单位,每个 Producer 可以向一个 Topic 发布一些消息。

这些概念和基本术语对于理解 Kafka 架构和运行原理非常重要,一定要牢记。

03Kafka 拓扑架构

一个典型的 Kafka 集群包含若干 Producer、Broker、Consumer Group,以及一个 ZooKeeper 集群。Kafka 通过 ZooKeeper 管理集群配置,选举 Leader,以及在 Consumer Group 发生变化时进行 Rebalance。Producer 使用 push 模式将消息发布到 Broker,Consumer 使用 pull 模式从 Broker 订阅并消费消息。典型架构图如下图所示:


从图中可以看出,典型的消息系统由生产者(Producer)、存储系统(Broker)和消费者(Consumer)组成。Kafka 作为分布式的消息系统支持多个生产者和消费者,生产者可以将消息分布到集群中不同节点的不同 Partition 上,消费者也可以消费集群中多个节点上的多个 Partition。在写消息时允许多个生产者写到同一个 Partition 中,但是读消息时一个 Partition 只允许被一个消费组中的一个消费者所消费,而一个消费者可以消费多个 Partition。也就是说同一个消费组下消费者对 Partition 是互斥的,而不同消费组之间是共享的。

Kafka 支持消息持久化存储,持久化数据保存在 Kafka 的日志文件中,在生产者生产消息后,Kafka 不会直接把消息传递给消费者,而是先要在 Broker 中进行存储。为了减少磁盘写入的次数,Broker 会将消息暂时缓存起来,当消息的个数或尺寸、大小达到一定阈值时,再统一写到磁盘上。这样不但提高了 Kafka 的执行效率,也减少了磁盘 IO 调用次数。

Kafka 中每条消息写到 Partition 中时,是顺序写入磁盘的,这个很重要。因为在机械盘中如果是随机写入的话,效率将很低,但如果顺序写入,那么效率却非常高。这种顺序写入磁盘机制是 Kafka 高吞吐率的一个很重要的保证。

04Topic 与 PartitionT

Kafka 中的 Topic 是以 Partition 的形式存放的,每一个 Topic 都可以设置它的 Partition 数量,该数量决定了组成 Topic 的 Log 的数量。推荐 Partition 的数量一定要大于同时运行的 Consumer 数量。另外,建议 Partition 的数量大于集群 Broker 的数量,这样消息数据就可以均匀地分布在各个 Broker 中了。

那么,Topic 为什么要设置多个 Partition 呢?这是因为 Kafka 是基于文件存储的,通过配置多个 Partition 可以将消息内容分散存储到多个 Broker 上,这样可以避免文件尺寸达到单机磁盘的上限。同时,将一个 Topic 切分成任意多个 Partitions,可以保证消息存储、消息消费的效率,因为越多的 Partitions 可以容纳更多的 Consumer,可有效提升 Kafka 的吞吐率。因此,将 Topic 切分成多个 Partitions 的好处是可以将大量的消息分成多批数据同时写到不同节点上,将写请求分担负载到各个集群节点。

在存储结构上,每个 Partition 在物理上对应一个文件夹,该文件夹下存储这个 Partition 的所有消息和索引文件。Partiton 命名规则为 Topic 名称 + 序号,第一个 Partiton 序号从 0 开始,序号最大值为 Partitions 数量减 1。

在每个 Partition(文件夹)中有多个大小相等的 Segment(段)数据文件,每个 Segment 的大小是相同的,但是每条消息的大小可能不相同。因此 Segment 数据文件中消息数量不一定相等。Segment 数据文件有两个部分组成:index file 和 data file,此两个文件一一对应,成对出现,后缀“.index”和“.log”分别表示为 Segment 索引文件和数据文件。

05Producer 生产机制

Producer 是消息和数据的生产者,当它发送消息到 Broker 时,会根据 Paritition 机制选择将其存储到哪一个 Partition。如果 Partition 机制设置的合理,所有消息都可以均匀分布到不同的 Partition 里,这样就实现了数据的负载均衡。如果一个 Topic 对应一个文件,那这个文件所在的机器 I/O 将会成为这个 Topic 的性能瓶颈;而有了 Partition 后,不同的消息可以并行写入不同 Broker 的不同 Partition 里,极大地提高了吞吐率。

06Consumer 消费机制

Kafka 发布消息通常有两种模式:队列模式(Queuing)和发布/订阅模式(Publish-Subscribe)。在队列模式下,只有一个消费组,而这个消费组有多个消费者,一条消息只能被这个消费组中的一个消费者所消费;而在发布/订阅模式下,可有多个消费组,每个消费组只有一个消费者,同一条消息可被多个消费组消费。

Kafka 中的 Producer 和 Consumer 采用的是 push(推送)、pull(拉取)的模式,即 Producer 只是向 Broker push 消息,Consumer 只是从 Broker pull 消息,push 和 pull 对于消息的生产和消费是异步进行的。pull 模式的一个好处是 Consumer 可自主控制消费消息的速率,同时 Consumer 还可以自己控制消费消息的方式是批量地从 Broker 拉取数据还是逐条消费数据。