无相兄
无相兄
7天前 · 3 人阅读
Apache Kafka

简介

Apache Kafaka 是一个分布式流平台(distributed streaming platform)

流平台有以下三个主要功能:

  • 发布和订阅流中的数据(records),和消息队列或者企业消息系统类似
  • 以容错和持久的方式保存流中的数据
  • 当流中的数据出现时,处理该流中的数据

Kafka主要有两类用途:

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

为了了解Kafka是如何实现上面的功能,让我们自下而上更深入的探索Kafka的这些能力。

一些关键概念:

  • Kafka以集群的方式运行在一个或多个服务器上,这些服务器可以跨多个数据中心
  • Kafka集群将流的数据(records)保存在名为 topics 的分类(categories)
  • 每条数据由键(Key)、值(Value)和时间戳(Timestamp)组成

Kafka 有四个核心API:

  • Producer API :该接口允许应用发布一个流数据到一个或多个 topics
  • Consumer API :该接口允许应用订阅一个或多个 topics 然后处理这些 topics 中的流数据
  • Streams API :该接口允许应用作为一个 流处理器(stream processor) ,从一个或多个 topics 的输入流中消费数据,然后转换并生产数据到一个或多个 topics 的输出流中
  • Connector API :该接口允许构建和运行可重用的生产者(Producer)或者消费者(Consumer),这些生产者或消费者讲Kafka中的 topics 和现有的应用或者数据系统(如数据库)连接起来。比如一个 connector 可以连接到一个关系型数据库从而可以捕捉到数据表中的任何变化,然后进行响应的处理

这些API的关系如下图:

Apache Kafka Core API

Kafka 使用一种简单、高效、语言无关的 TCP协议 来完成客户端和服务端的数据交换。这是一种版本化并且向后兼容的协议。Kafka 默认提供了 Java 客户端,并且也有大部分其他语言可用的客户端。

Topics 和 Logs

我们首先来看看 Kafka 对流数据 ( a stream of records) 的提供的核心抽象 —— Topic

Topic 是数据被发布到 Kafka 的一个分类。Topics 可以有零个、一个或者多个消费者(Consumers),这些消费订阅(subscribe)被写入 topics 的数据。

对每个 topic, Kafka 集群维护了一个分区的记录(log),如下图所示:

Anatomy of a Topic

每一个分区 (Partition) 都是一个有序的、不可变的数据序列,这些数据被不断的添加到序列的尾部,每个分区都是一种结构化的 提交记录 (commit log)。 在分区中的每一条数据都被赋予了一个连续的数字ID,这个ID叫做 偏移量 (offset) 。 偏移量唯一的标识了每个分区中的每条数据。

Kafka 集群会持久化保存所有被发布到 topics 中的数据(无论这些数据是否已经被消费),数据的保存时间是可以配置的。比如,如果保留周期设置为两天,那么一条数据被发布到 topic 以后,在两天内都是可以被消费的,两天以后会被 Kafka 丢弃以释放磁盘空间。Kafka 的性能在数据大小方面是恒定的,所以长时间的存储数据不是问题。

Anatomy of a Partition

实际上,每个消费者 (Consumer) 唯一保留的数据就是该消费者在记录 (log) 中的偏移量 (offset)。该偏移量由消费者自身控制:一般情况下,消费者会在读取数据的时候线性地增加其偏移量,但实际上,由于偏移量是由消费者自身控制,因此它可以按照自己喜欢的任何顺序来消费数据 (records) 。比如,消费者可以把偏移量重置为以前的位置来重新处理过去的数据,或者跳到最近的数据从“现在”开始消费。

这些功能的组合意味着 Kafka 的消费者非常轻量级,他们可以随意的运行和停止而对集合或其他消费者没有太大影响。比如,你可以使用自带的命令行工具的命令 tail 来获取任何 topic 的内容而不会改变现有的消费者。

记录(Log) 中的分区有几个目的。第一个是允许 Log 扩展到超过适合单个服务器的大小。第二个是每个分区的大小必须合适它所在的服务器,但是一个 topic 可以有许多分区,所以一个 topic 可以有任意数量的数据。

分布式

记录(Log) 的分区分布在 Kafka 集群的服务器中,每个服务器处理数据并向分区的共享发起请求。每个分区都在数量可配置的服务器中进行复制,以实现容错。

每个分区都有一个服务器作为 Leader,其他服务器作为 FollowersLeader 负责处理分区的所有读写请求,Followers 仅仅被动地从 Leader 复制数据。 如果 Leader 挂掉了,其中一个 Followers 会自动变成新的 Leader。每个服务器都扮演某些分区中的 Leader 和某些分区中的 Followers,所以负载在集群中得到了很好的均衡。

Producers

Producers 发布数据到它们选择的 topics 中。 Producer 决定数据放到哪个 topic 的哪个分区(Partition) 中。可以通过流行的 round-robin 来完成,也可以通过某些语义分区功能来实现。

Consumers

Consumers 使用 Consumer group 的名字来标识自己,并且每个发布到 topic 的数据 (record) 都会被传递到每个 consumer group 中的 一个 消费者实例。消费者实例可以在单独的进行中或者在不同的机器中。

  • 如果所有的消费者实例都在同一个 consumer group 中,那么数据将会轮流被组中的消费者消费。
  • 如果所有的消费者实例都在不同的 consumer group 中,那么每一条数据都会被所有的消费者消费,即广播。