无相兄
无相兄
2月前 · 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 中,那么每一条数据都会被所有的消费者消费,即广播。
Consumer

一个有两个服务器的 Kafka 集群,托管了四个分区(P0 - P3),包含了两个 consumer group,第一个组拥有两个消费者实例,第二个组拥有四个消费者实例。

然而,更常见的是,每个 topic 有少量的 consumer group, 每个组都由许多的消费者实例组成,以实现可伸缩性和容错性。这和传统的“发布-订阅”模式没有什么不同,只不过订阅者不是一个单独的进程,而是一个消费者集群。

在 Kafka 中实现消费的方式是通过在消费者实例划分 Log 中的分区,这样每个实例在任何时间都是“公平等分”的独占消费者。维护消费者组中成员资格的过程是由 Kafka 自己的协议动态处理的。如果有新的实例加入到组中,新的实例将会接管一些其他成员的分区;如果有实例挂掉了,该实例管理的分区将会被分给其他实例。

Kafka 只提供分区中的数据总记录,而不是在不同 topic 不同分区之间的记录。

多用户

Kafka 可以被部署为多用户解决方案。可以通过配置哪些 topic 可以生成或消费数据来启用多用户功能。多用户也支持配额。管理员可以定义和强制执行配额,以控制客户端使用的 broker 资源。

保证

Kafka 提供了以下保证:

  • 生产者发送到某个 topic 分区的消息将按照其发送的顺序依次添加
  • consumer 实例按照它们储存在 log 中的顺序查看数据
  • 对于具有复制因子 N 的 topic,我们会允许最多 N - 1 个服务器故障,而不会丢失任何提交到 log 的数据

Kafka 作为消息系统(消息队列)

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

消息传统上有两种模型:队列和发布 - 订阅。在队列中,消费者池可以从服务器读取并处理数据个;在发布 - 订阅中,数据被广播给所有消费者。这两种模型中的每一种都有优点和缺点。队列的优势在于它允许在多个消费者实例上处理数据,从而可以扩展数据的处理。但是,队列不是多用户的,一旦一个消费者读取数据,该数据就被使用。发布 - 订阅允许将数据广播到多个订阅者,但由于每条消息都发送给每个订阅者,因此无法进行扩展处理。

Kafka 的消费者组概念概括了传统消息系统的两个概念。与队列一样,消费者组允许将数据处理划分为一组进程。与发布 - 订阅一样,Kafka 允许向多个消费者组广播消息。

Kafka 模型的优势在于每个 topic 都具有这些属性,它可以扩展数据处理并且也是多用户的。

与传统的消息系统相比,Kafka 有更强的顺序保证。

传统队列在服务器上按顺序保留记录,如果多个消费者从队列中消耗,则服务器按照存储顺序分发数据。但是,虽然服务器按顺序分发数据,但是数据是异步传递给消费者的,因此它们可能会在不同的消费者处出现问题。这实际上意味着在存在并行消费的情况下丢失数据的顺序。消息系统通常通过具有“独占消费者”概念来解决这个问题,该概念只允许一个进程从队列中消费数据,这样就没有了并行性。

在 Kafka 中。通过在 topic 中具有并行性概念 分区 ,Kafka 能够在消费者流程池中提供顺序保证和负载均衡。这是通过将 topic 中的分区分配给消费者组中的消费者来实现的,以便每个分区仅由该组中的一个消费者使用。这样,就可以确保消费者是该分区的唯一读取者并按顺序使用数据。由于有许多分区,便可以平衡许多消费者实例的负载。但请注意,消费者组中的消费者实例不能超过分区。

Kafka 作为存储系统

任何允许 发布与消费 消息解耦的消息队列,实际上扮演了一个消息的存储系统。 Kafka的不同之处在于它是一个非常好的存储系统。

写入 Kafka 的数据将写入磁盘并进行复制以实现容错。 Kafka 允许生产者等待确认,以便在完全复制之前写入认为是不完整的,直到数据全部复制到所有服务器上。

Kafka 的磁盘结构很好地使用了伸缩,无论服务器上有50 KB还是50 TB的数据,Kafka 的磁盘性能影响都差不多。

Kafka 是一种专用于高性能,低延迟提交日志(commoit log)存储,复制和传播的专用分布式文件系统。

收藏 0
数据 topic 消费者 kafka 服务器 分区
评论 ( 0 )