Kafka基本架构及原理

2022-09-07 09:15:59

Kafka 是一个消息系统,原本开发自LinkedIn,用作 LinkedIn 的事件流(Event Stream)和运营数据处理管道(Pipeline)的基础。现在它已被多家不同类型的公司作为多种类型的数据管道和消息系统使用。

Kafka 是一种分布式的,基于发布/订阅的消息系统。主要设计目标如下:

  • 以时间复杂度为 O(1) 的方式提供消息持久化能力,即使对 TB 级以上数据也能保证常数时间复杂度的访问性能。
  • 高吞吐率。即使在非常廉价的商用机器上也能做到单机支持每秒 100K 条以上消息的传输。
  • 支持 Kafka Server 间的消息分区,及分布式消费,同时保证每个 Partition 内的消息顺序传输。
    同时支持离线数据处理和实时数据处理。
  • 横向扩展:支持在线水平扩展(Scale out)。

消息系统

为何使用消息系统

  • 解耦:在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
  • 冗余:有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入 - 获取 - 删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
  • 扩展性:因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。
  • 灵活性 & 峰值处理能力:在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
  • 可恢复性:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
  • 顺序保证:在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka 保证一个Partition内的消息的有序性。
  • 缓冲:在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行———写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。
  • 异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

Push vs Pull

作为一个消息系统,Kafka 遵循了传统的方式,选择由 Producer 向 broker push 消息并由 Consumer 从 brokerpull消息。一些日志收集系统(logging-centric system),比如 Facebook 的Scribe和 Cloudera 的Flume,采用push模式。事实上,push模式和pull模式各有优劣。

push 模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的。push 模式的目标是尽可能以最快速度传递消息,但是这样很容易造成 Consumer 来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 Consumer 的消费能力以适当的速率消费消息

对于 Kafka 而言,pull 模式更合适。pull 模式可简化 broker 的设计,Consumer 可自主控制消费消息的速率,同时 Consumer 可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。

Kafka

基本架构

  • Broker:Kafka 集群包含一个或多个服务器,这种服务器被称为 broker
  • Topic:每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic。(物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处)
  • Partition:Parition(分片)是物理上的概念,每个 Topic 包含一个或多个 Partition.
  • Producer:负责发布消息到 Kafka broker
  • Consumer:消息消费者,向 Kafka broker 读取消息的客户端。
  • Consumer Group:每个 Consumer 属于一个特定的消费者组Consumer Group(可为每个 Consumer 指定 group name,若不指定 group name 则属于默认的 group)。

在这里插入图片描述

一个典型的 Kafka 集群中包含若干 Producer(可以是 web 前端产生的 Page View,或者是服务器日志,系统 CPU、Memory 等),若干 broker(Kafka 支持水平扩展,一般 broker 数量越多,集群吞吐率越高),若干 Consumer Group,以及一个 Zookeeper 集群。
Kafka 通过 Zookeeper 管理集群配置,选举 leader,以及在 Consumer Group 发生变化时进行rebalance

如上图所示,Producer 使用push模式将消息发布到 broker,Consumer 使用pull模式从 broker 订阅并消费消息。

消息持久化

Kafka 在消息的存储和缓存中重度依赖文件系统。

相对于竭尽所能的维护内存内结构而且要时刻注意在空间不足时谨记要将它们flush到文件系统中,我们可以颠覆这种做法。所有的数据被直接写入文件系统上一个可暂不执行磁盘 flush 操作的持久化日志文件中。实际上这意味着这些数据是被传送到了内核的页缓存上。
这种基于页缓存的设计可以参见在 这篇关于Varnish的论文

Kafka 采用顺序写磁盘的方法,将持久化队列建立在简单的读取和向文件后追加两种操作之上(即将每条消息都被 append 到该 Partition 中),这和日志解决方案相同,因此效率非常高。这种结构的优点在于所有的操作复杂度都是O(1),而且读操作不会阻塞写操作,读操作之间也不会互相影响。

Kafka也不是partition一有数据就立马将数据写到磁盘上,它会先缓存一部分,等到足够多数据量或等待一定的时间再批量写入(flush)。

经验证,顺序写磁盘效率比随机写内存还要高,这是 Kafka 高吞吐率的一个很重要的保证。

Topic & Partition

Topic 在逻辑上可以被认为是一个消息队列,每条消费都必须指定它的 Topic,可以简单理解为必须指明把这条消息放进哪条消息队列里。为了使得 Kafka 的吞吐率可以线性提高,物理上把 Topic 分成一个或多个 Partition,每个 Partition 在物理上对应一个文件夹,该文件夹下存储这个 Partition 的所有消息和索引文件。

备份分区(Partition)仅仅用作于备份,不做读写。如果某个Broker挂了,那就会选举出其他Broker的 Partition 来作为主分区,这就实现了高可用。

producer 消息路由

producer 发送消息到 broker 时,会根据分区算法选择将其存储到哪一个 partition。如果 Partition 机制设置合理,所有消息可以均匀分布到不同的 Partition 里,从而达到负载均衡的效果。其路由机制为:

  1. 指定了 patition,则直接使用
  2. 未指定 patition 但指定 key,通过对 key 的 value 进行hash 选出一个 patition
  3. patition 和 key 都未指定,使用轮询选出一个 patition。

Consumer

kafka 的分配单位是 patition。每个 consumer 都属于一个 group,一个 partition 只能被同一个 group 内的一个 consumer 所消费(即保证了一个消息只能被 group 内的一个 consuemr 所消费)

在这里插入图片描述

实际上,Kafka 的设计理念之一就是同时提供离线处理和实时处理。根据这一特性,可以使用Storm这种实时流处理系统对消息进行实时在线处理,同时使用Hadoop这种批处理系统进行离线处理,还可以同时将数据实时备份到另一个数据中心,只需要保证这三个操作所使用的 Consumer 属于不同的 Consumer Group 即可。

Kafka 在 Linkedin 的一种简化部署示意图。


参考文档:

  1. Kafka
  2. Kafka基本架构及原理
  3. 全网最通俗易懂的Kafka入门
  4. kafka学习笔记:知识点整理
  5. 你能说出 Kafka 这些原理吗?
  6. Kafka 设计解析(一):Kafka 背景及架构介绍
  • 作者:
  • 原文链接:https://tillend.blog.csdn.net/article/details/108298413
    更新时间:2022-09-07 09:15:59