Apache Kafka 介绍

Apache Kafka®是一个分布式流平台。这到底是什么意思呢? 流媒体平台有三个关键功能:

  • 发布和订阅记录流,类似于消息队列或企业消息传递系统。
  • 以容错的持久方式存储记录流。
  • 当记录发生时处理它们的流。

Kafka通常用于两大类应用程序:

  • 构建实时流数据管道,在系统或应用程序之间可靠地获取数据
  • 构建转换或响应数据流的实时流应用程序

为了理解Kafka是如何做这些事情的,让我们深入探索一下Kafka的自底向上的能力。

首先是一些概念:

  • Kafka作为一个集群运行在一个或多个服务器上,这些服务器可以跨越多个数据中心。
  • Kafka集群将记录流存储在称为主题的类别中。
  • 每个记录由一个键、一个值和一个时间戳组成。

Kafka 有四个核心 api:

Apache Kafka 介绍

  • Producer API 允许应用程序将记录流发布到一个或多个 Kafka 主题。
  • Consumer API 允许应用程序订阅一个或多个主题,并处理产生给它们的记录流。
  • Streams API 允许应用程序充当流处理器,使用一个或多个主题的输入流,并生成一个或多个输出主题的输出流,从而有效地将输入流转换为输出流。
  • Connector API 允许构建和运行将 Kafka 主题连接到现有应用程序或数据系统的可重用生产者或消费者。例如,到关系数据库的连接器可能捕获对表的每个更改。

在Kafka中,客户端和服务器之间的通信是通过一个简单的、高性能的、语言无关的TCP协议来完成的。此协议经过版本控制,并保持与旧版本的向后兼容性。我们为 Kafka 提供了一个 Java 客户端,但是客户端有多种语言。

1、主题与日志

让我们首先深入了解Kafka为记录流提供的核心抽象 —— 主题。

Topic 是记录发布到的类别或提要名称。Kafka 中的主题始终是多订阅者的;也就是说,一个主题可以有0个、1个或多个订阅其所写入数据的使用者。

对于每个主题,Kafka 集群维护一个分区日志,如下所示:

Apache Kafka 介绍
每个分区都是一个有序的、不可变的记录序列,这些记录被连续地附加到一个结构化的提交日志中。分区中的每条记录都被分配一个连续的id号,称为偏移量,该偏移量唯一地标识分区中的每条记录。

Kafka 集群使用可配置的保留期持久地保存所有已发布的记录(不管它们是否已被使用)。例如,如果保留策略设置为两天,那么在记录发布后的两天内,它是可用的,在此之后,它将被丢弃以释放空间。Kafka 的性能在数据大小方面是稳定的,所以长时间存储数据不是问题。

事实上,在每个消费者的基础上保留的唯一元数据是该消费者在日志中的偏移量或位置。此偏移由使用者控制:通常,使用者在读取记录时将线性地推进其偏移,但实际上,由于位置由使用者控制,因此它可以按自己喜欢的任何顺序使用记录。例如,使用者可以重置为较早的偏移量来重新处理来自过去的数据,或者跳到最近的记录并从“now”开始消费。
Apache Kafka 介绍

这些特性的组合意味着 Kafka 消费者非常便宜——他们可以来来去去,而不会对集群或其他消费者造成太大影响。例如,您可以使用我们的命令行工具来“跟踪”任何主题的内容,而不需要更改任何现有使用者所使用的内容。

日志中的分区有几个用途。首先,它们允许日志扩展到一个服务器所能容纳的范围之外。每个单独的分区必须适合承载它的服务器,但是一个主题可能有多个分区,因此它可以处理任意数量的数据。其次,它们充当并行的单位——在这一点上稍微多一点。

2、分布式

日志的分区分布在 Kafka 集群中的服务器上,每个服务器处理数据和共享分区的请求。为了容错,每个分区被复制到大量可配置的服务器上。

每个分区有一个充当 “leader” 的服务器和零个或多个充当 “follower” 的服务器。leader 处理分区的所有读和写请求,而 follower 被动地复制 leader。如果 leader 失败,其中一个 follower 将自动成为新的 leader。每个服务器充当它的一些分区的 leader 和其他分区的 follews,因此集群内的负载非常平衡。

3、Geo-Replication

Kafka Mirror Maker为集群提供地理复制支持。使用 MirrorMaker,消息可以跨多个数据中心或云区域进行复制。您可以在用于备份和恢复的主动/被动场景中使用它;或者在活动/活动场景中,将数据放置到离用户更近的地方,或者支持数据位置需求。

4、生产者 – Producers

生产者将数据发布到他们选择的主题。生产者负责选择将哪个记录分配给主题中的哪个分区。这可以以循环的方式来完成,只是为了平衡负载,也可以根据某种语义划分函数(比如基于记录中的某个键)来完成。更多关于分区的用法,我们稍后再讨论!

5、消费者 – Consumers

消费者使用消费者组名称标记自己,发布到主题的每个记录将传递到每个订阅使用者组中的一个使用者实例。使用者实例可以在单独的进程中,也可以在单独的机器上。

如果所有消费者实例具有相同的消费者组,那么记录将有效地在使用者实例上进行负载平衡。

如果所有的消费者实例都有不同的消费者组,那么每个记录将被广播到所有的消费者进程。
Apache Kafka 介绍
一个包含四个分区(P0-P3)和两个消费者组的两台服务器 Kafka 集群。消费者组 A 有两个使用者实例,而组B有四个。

然而,更常见的是,我们发现主题有少量的消费者组,每个“逻辑订阅者”对应一个用户组。每个组由许多用于可伸缩性和容错的消费者实例组成。这只不过是发布-订阅语义,其中订阅者是一个消费者集群,而不是单个进程。

Kafka 中实现消费的方法是在消费者实例的日志中划分分区,这样每个实例在任何时候都是分区“公平共享”的唯一消费者。这个保持组成员身份的过程是由 Kafka 协议动态处理的。如果新的实例加入组,它们将从组的其他成员那里接管一些分区;如果一个实例死亡,它的分区将分配给其余的实例。

Kafka 只提供分区内记录的总顺序,而不提供主题中不同分区之间的总顺序。对大多数应用程序来说,按分区排序和按键分区数据的能力已经足够了。但是,如果您需要记录的总顺序,则可以使用只有一个分区的主题来实现这一点,尽管这意味着每个使用者组只有一个使用者进程。

6、多租房 – Multi-tenancy

您可以将 Kafka 部署为一个多租户解决方案。通过配置哪些主题可以生成或使用数据,可以启用多租户。还有对限额的操作支持。管理员可以对请求定义和强制执行限额,以控制客户端使用的代理资源。有关更多信息,请参阅安全文档。

7、担保 – Guarantees

在高层 Kafka 给出了以下保证:

  • 生产者发送到特定主题分区的消息将按照发送的顺序追加。也就是说,如果记录M1是由与记录M2相同的生产者发送的,并且M1是先发送的,那么M1的偏移量将比M2低,并出现在日志的前面。
  • 消费者实例按记录在日志中存储的顺序查看记录。
  • 对于具有复制因子N 的主题,我们将容忍至多N-1个服务器故障,而不会丢失提交到日志的任何记录。

关于这些保证的更多细节在文档的设计部分中给出。

8、Kafka 作为一个消息系统

Kafka 的流概念与传统的企业消息传递系统相比如何?

传统的消息传递有两种模式: 队列 和 发布-订阅。在队列中,一个使用者池可以从一个服务器读取数据,而每个记录都将被发送到其中的一个服务器; 在发布-订阅中,记录被广播给所有消费者。这两种模式各有优缺点。队列的优点是它允许您在多个使用者实例上划分数据处理,这使您可以扩展处理。不幸的是,队列不是多订阅者的—一旦一个进程读取了它丢失的数据。Publish-subscribe 允许您将数据广播到多个进程,但是由于每个消息都传递到每个订阅者,因此无法扩展处理。

Kafka 中的消费者群体概念概括了这两个概念。与队列一样,消费者组允许您将处理划分到一组进程(消费者组的成员)上。与发布-订阅一样,Kafka 允许您向多个消费者组广播消息。

Kafka 模型的优点是每个主题都有这两种属性 —— 它可以扩展处理,而且是多订阅者的——没有必要选择其中之一。

Kafka 也比传统的消息传递系统有更强的订购保证。

传统队列在服务器上按顺序保留记录,如果多个使用者从队列中消费,则服务器按存储记录的顺序分发记录。然而,尽管服务器按顺序分发记录,但这些记录是异步传递给使用者的,因此它们可能在不同的使用者上不按顺序到达。这实际上意味着记录的顺序在并行使用时丢失。消息传递系统通常通过“独占消费者”的概念来解决这个问题,该概念只允许一个进程从队列中消费,但这当然意味着处理中不存在并行性。

Kafka 做得更好。通过主题中的并行性(分区)概念,Kafka 能够在用户进程池上提供排序保证和负载平衡。这是通过将主题中的分区分配给消费者组中的消费者来实现的,这样每个分区正好由组中的一个消费者使用。通过这样做,我们可以确保消费者是该分区的唯一读取者,并按顺序使用数据。由于有许多分区,这仍然可以在许多消费者实例上平衡负载。但是请注意,在一个消费者组中不能有比分区更多的消费者实例。

9、Kafka 作为一个存储系统

任何允许发布消息与使用消息解耦的消息队列都有效地充当了动态消息的存储系统。Kafka 的不同之处在于它是一个非常好的存储系统。

写入 Kafka 的数据被写入磁盘并复制,以获得容错能力。Kafka允许生产者等待确认,直到完全复制并保证即使写入的服务器失败,写入也不会被认为是完成的。

Kafka 使用的磁盘结构具有伸缩性 —— 无论您在服务器上有 50 KB 还是 50 TB 的持久数据,Kafka 都将执行相同的操作。

由于认真对待存储并允许客户端控制其读位置,您可以将 Kafka 看作一种专用于高性能、低延迟提交日志存储、复制和传播的分布式文件系统。

10、Kafka 用于流处理

仅仅读取、写入和存储数据流是不够的,其目的是实现流的实时处理。

在 Kafka 中,流处理器是指从输入主题中获取连续的数据流,对这个输入执行一些处理,并产生连续的数据流来输出主题。

例如,一个零售应用程序可能接收销售和发货的输入流,并根据这些数据计算出重新订购和价格调整的输出流。

可以直接使用生产者和消费者 api 进行简单的处理。然而,对于更复杂的转换,Kafka 提供了一个完全集成的Streams API。这允许构建进行非平凡处理的应用程序,这些处理可以计算流的聚合或将流连接在一起。

此功能有助于解决此类应用程序面临的难题:处理无序数据、在代码更改时重新处理输入、执行有状态计算等。

streams API 构建在 Kafka 提供的核心原语之上:它使用生产者和消费者API进行输入,使用Kafka进行有状态存储,并在流处理器实例之间使用相同的组机制进行容错。

11、总结

这种消息传递、存储和流处理的组合看起来很不寻常,但它对于 Kafka 作为流平台的角色来说是必不可少的。

像 HDFS 这样的分布式文件系统允许存储静态文件进行批处理。实际上,这样的系统允许存储和处理来自过去的历史数据。

传统的企业消息传递系统允许处理在您订阅之后到达的未来消息。以这种方式构建的应用程序在未来的数据到达时进行处理。

Kafka 结合了这两种功能,这种结合对于 Kafka 作为流应用程序的平台和流数据管道来说都是至关重要的。

通过结合存储和低延迟订阅,流应用程序可以以相同的方式处理过去和未来的数据。也就是说,单个应用程序可以处理历史的、存储的数据,而不是在到达最后一条记录时结束,而是在未来的数据到达时继续处理。这是流处理的一个通用概念,它包含批处理和消息驱动的应用程序。

类似地,对于流数据管道,实时事件订阅的组合使得在非常低延迟的管道中使用Kafka成为可能;但是,可靠地存储数据的能力使其能够用于必须保证数据交付的关键数据,或者用于与只定期加载数据或可能为了维护而长时间停机的脱机系统的集成。流处理设施使得在数据到达时转换数据成为可能。

原文地址:http://kafka.apache.org/intro