1. GETTING STARTED
1.1 Introduction
Apache Kafka® is a distributed streaming platform. What exactly does that mean?(Apache Kafka®是一个分布式流平台。这到底是什么意思?)
流平台有三个关键功能:
- 发布和订阅记录流,类似于消息队列或企业消息系统。
- 以容错、持久的方式存储记录流。
- 在记录流发生时处理它们。
Kafka通常用于两大类应用程序:
- 构建在系统或应用程序之间可靠地获取数据的实时流数据管道。
- 构建对数据流进行转换或响应的实时流应用程序。
为了理解Kafka是如何做这些事情的,让我们从下到上深入研究一下Kafka的能力。
首先是几个概念:
- Kafka作为集群运行在一个或多个可以跨多个数据中心服务器上。
- Kafka集群以称为主题( topics)的类别存储记录(records)流。
- 每个记录由一个键、一个值和一个时间戳组成。
Kafka有四个核心APIs:
- Producer API 允许应用程序将一个记录流发布到一个或多个Kafka主题。
- Consumer API 允许应用程序订阅一个或多个主题,并处理向它们生成的记录流。
- Streams API 允许一个应用程序充当一个流处理器-- stream processor,消费来自一个或多个主题的输入流,并将输出流生成到一个或多个输出主题,从而有效地将输入流转换为输出流。
- Connector API 允许构建和运行可重用的生产者或消费者,这些生产者或消费者将Kafka主题连接到现有的应用程序或数据系统。例如,到关系数据库的连接器可能会捕获对表的每个更改。
在Kafka中,客户机和服务器之间的通信是通过一个简单、高性能、语言无关的TCP协议来完成的。此协议已版本化,并保持与旧版本的向后兼容性。我们为Kafka提供了一个Java客户端,但是客户端可以使用多种语言。
让我们首先深入了解Kafka为记录流(主题)提供的核心抽象。
主题是发布记录的类别或提要名称。Kafka中的主题始终是多订阅者的;也就是说,一个主题可以有零个、一个或多个 订阅写入它的数据 的消费者。
对于每个主题,kafka集群都维护一个分区日志,如下所示:
每个分区都是一个有序的、不可变的记录序列,这些记录连续附加到一个结构化提交日志中。每个分区中的记录都被分配一个称为偏移量-- offset 的顺序ID号,该偏移量唯一地标识分区中的每个记录。
Kafka集群使用一个可配置的保留期持久地保存所有已发布的记录(无论它们是否已被消费)。例如,如果保留策略被设置为两天,那么在记录发布后的两天内,它是可用的,在此之后,它将被丢弃以释放空间。Kafka的性能在数据大小方面是稳定的,所以长时间存储数据不是问题。
实际上,在每个消费者的基础上保留的惟一元数据是该消费者在日志中的偏移量或位置。这个偏移量由消费者控制:通常消费者在读取记录时将线性地推进它的偏移量,但是,实际上,由于位置由使用者控制,所以它可以按照自己喜欢的任何顺序使用记录。例如,消费者可以重置为较早的偏移量,以便重新处理来自过去的数据,或者跳到最近的记录,从“现在”开始消费。
这些特性的组合意味着Kafka消费者非常便宜——他们可以来来去去,而不会对集群或其他消费者造成太大影响。例如,您可以使用我们的命令行工具“tail”任何主题的内容,而不需要更改任何现有消费者所使用的内容。
日志中的分区有几个用途。首先,它们允许日志扩展到超出单个服务器所能容纳的大小。每个单独的分区必须适合承载它的服务器,但是一个主题可能有多个分区,因此它可以处理任意数量的数据。其次,它们在一点上更像是并行的单位。
Distribution(分布)
日志的分区分布在Kafka集群中的服务器上,每个服务器处理数据并请求共享分区。每个分区都在可配置数量的服务器上进行复制,以实现容错性。
每个分区都有一个充当“leader”的服务器和零个或多个充当“follower”的服务器。leader处理此分区的所有读和写请求,而follower被动地复制leader。如果leader失败,其中一个follower将自动成为新的leader。每个服务器充当它的一些分区的领导者和其他分区的追随者,因此集群内的负载非常平衡。
Kafka MirrorMaker为集群提供地理复制支持。使用MirrorMaker,消息可以跨多个数据中心或云区域复制。您可以在用于备份和恢复的主动/被动场景中使用它;或在主动/主动场景中,将数据放置到离用户更近的位置,或支持数据本地化需求。
生产者将数据发布到它们选择的主题。生产者负责选择要把哪个记录分配给主题的哪个分区。这可以通过循环方式来完成,只是为了平衡负载,也可以根据语义分区函数(比如基于记录中的某个键)来完成。稍后将详细介绍分区的使用!
消费者使用消费者组名称给它们自己贴标签,每个发布到主题的记录被交付到每个订阅消费者组中的一个消费者实例。消费者实例可以位于单独的进程中,也可以位于单独的机器上。
如果所有消费者实例都具有相同的消费者组,那么记录将有效地在消费者实例上进行负载平衡。
如果所有消费者实例都有不同的消费者组,那么每个记录都将广播到所有消费者进程。
一个包含四个分区(P0-P3)的两台服务器Kafka集群,包含两个用户组。消费者组A有两个消费者实例,而B组有四个。
然而,更常见的情况是,我们发现主题有少量的使用者组,每个“逻辑订阅者”对应一个用户组。每个组由许多可伸缩性和容错的消费者实例组成。这只不过是发布-订阅语义,其中订阅者是一组消费者,而不是单个流程。
Kafka中实现消费的方法是在消费者实例上划分日志中的分区,这样每个实例在任何时间点都是分区的“公平共享”的唯一使用者。这个维护组成员关系的过程由Kafka协议动态处理。如果新实例加入组,它们将从组的其他成员那里接管一些分区;如果一个实例死亡,它的分区将分配给其余的实例。
Kafka只提供一个分区内记录的总顺序,而不是主题中不同分区之间的总顺序。每个分区的排序加上按键划分数据的能力就足够了。但是,如果您需要一个 记录的总顺序,则可以使用只有一个分区的主题来实现这一点,尽管这意味着每个消费者组只有一个消费者进程。
您可以将Kafka部署为一个多租户解决方案。通过配置哪些主题可以生产或使用数据,可以启用多租户。还有对配额的操作支持。管理员可以对请求定义和强制配额,以控制客户端使用的代理资源。有关更多信息,请参见 security documentation:https://kafka.apache.org/documentation/#security。
在高层次上,Kafka提供以下保证:
- 生产者发送到特定主题分区的消息将按发送顺序追加。也就是说,如果一个记录M1是由与记录M2相同的生产商发送的,并且M1是首先发送的,那么M1的偏移量将小于M2,并在日志中出现得更早。
- 消费者实例按记录在日志中的存储顺序查看记录。
- 对于具有复制因子N的主题,我们将容忍最多N-1个服务器故障,而不会丢失提交到日志的任何记录。
有关这些保证的更多详细信息,请参见文档的设计部分。
Kafka的流概念与传统的企业消息传递系统相比如何?
消息传递传统上有两种模型: queuing 和 publish-subscribe 。在队列中,一个消费者池可以从一个服务器读取数据,并且每个记录将被发送到其中一个消费者;在publish-subscribe中,记录被广播给所有消费者。这两种模式各有优缺点。排队的优势在于,它允许您在多个使用者实例上划分数据处理,从而允许您扩展处理。不幸的是,一旦一个进程读取了它丢失的数据,队列就不是多订阅者。发布-订阅允许您将数据广播到多个进程,但是由于每个消息都发送到每个订阅者,因此无法扩展处理。
Kafka中的消费者组概念概括了这两个概念。与队列一样,消费者组允许您将处理划分到一组进程(消费者组的成员)上。与发布-订阅一样,Kafka允许您向多个消费者组广播消息。
Kafka模型的优点在于,每个主题都具有这些特性,可以进行规模化处理,而且是多用户的,不需要选择其中一个主题。
Kafka也比传统的消息传递系统有更强的顺序保证。
传统队列在服务器上按顺序保留记录,如果多个消费者从队列中消费,则服务器按存储记录的顺序分发记录。然而,尽管服务器按顺序分发记录,但是这些记录是异步传递给消费者的,因此它们可能在不同的消费者上出现顺序错误。这实际上意味着记录的顺序在并行消费时丢失。消息传递系统通常通过“独占消费者”的概念来解决这个问题,该概念只允许一个进程从队列中消费,但这当然意味着处理中不存在并行性。
Kafka做得更好。通过在主题中具有并行性(分区)的概念,Kafka能够在消费者进程池上提供排序保证和负载平衡。这是通过将主题中的分区分配给消费者组中的消费者来实现的,以便每个分区恰好由组中的一个消费者消费。通过这样做,我们确保此消费者是该分区的唯一读取者,并按顺序消费数据。由于有许多分区,这仍然可以在许多消费者实例上平衡负载。但是请注意,在一个消费者组中不能有多于分区的消费者实例。
Kafka as a Storage System
任何允许发布与使用分离的消息的消息队列都有效地充当正在运行的消息的存储系统。Kafka的不同之处在于它是一个非常好的存储系统。
写入Kafka的数据被写入磁盘并复制以获得容错性。Kafka允许生产者等待确认,这样即使写入的服务器失败,写入也不会被认为是完整的,除非它被完全复制并保证保持不变。
Kafka使用的磁盘结构伸缩性很好,无论服务器上有50KB还是50TB的持久数据,Kafka都会执行相同的操作。
由于认真对待存储并允许客户机控制其读取位置,您可以将Kafka视为一种专用的分布式文件系统,专门用于高性能、低延迟提交日志存储、复制和传播。
有关Kafka提交日志存储和复制设计的详细信息,请阅读本页。
Kafka for Stream Processing
仅仅读取、写入和存储数据流是不够的,其目的是实现对数据流的实时处理。
在Kafka中,流处理器是指从输入主题获取连续的数据流,对这个输入执行一些处理,并产生连续的数据流到输出主题 的任何东西。
例如,一个零售应用程序可能接受销售和发货的输入流,并根据这些数据计算出重新订购和价格调整的输出流。
可以直接使用生产者和消费者APIs进行简单的处理。但是对于更复杂的转换,Kafka提供了一个完全集成的Streams API。这允许构建进行非平凡处理的应用程序,这些处理可以计算流之外的聚合或将流连接在一起。
此工具有助于解决此类应用程序面临的难题:处理无序数据、在代码更改时重新处理输入、执行状态计算等。
streams API构建在Kafka提供的核心原语之上:它使用生产者和消费者API进行输入,使用Kafka进行有状态存储,并使用相同的组机制在流处理器实例之间进行容错。
Putting the Pieces Together
这种消息、存储和流处理的组合可能看起来很不寻常,但对于Kafka作为流平台的角色来说,这是至关重要的。
像HDFS这样的分布式文件系统允许存储静态文件进行批处理。这样的系统可以有效地存储和处理过去的历史数据。
传统的企业消息传递系统允许处理订阅后将到达的未来消息。以这种方式构建的应用程序在未来数据到达时对其进行处理。
Kafka结合了这两种功能,对于Kafka作为流式应用程序平台以及流式数据管道的使用来说,两者的结合都是至关重要的。
通过结合存储和低延迟订阅,流式应用程序可以以相同的方式处理过去和将来的数据。这是一个可以处理历史存储数据的应用程序,但当它到达最后一条记录时,它可以继续处理未来数据,而不是停止。这是流处理的一个广义概念,包含批处理和消息驱动应用程序。
同样,对于流数据管道,订阅实时事件的组合使使用Kafka处理非常低延迟的管道成为可能;但是,可靠地存储数据的能力使其能够用于必须保证数据交付的关键数据,或者用于与只定期加载数据的离线系统集成,或者可能在很长一段时间内停机以进行维护。流处理设施使得在数据到达时转换数据成为可能。
有关Kafka提供的保证、API和功能的更多信息,请参阅此文档的其余部分。
1.2 Use Cases
下面是对ApacheKafka®的一些流行用例的描述。有关这些领域的概述,请参阅 this blog post:https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/.
Kafka可以很好地替代传统的消息代理。消息代理用于各种各样的原因(将处理与数据生成器解耦,缓冲未处理的消息,等等)。与大多数消息传递系统相比,Kafka具有更好的吞吐量、内置分区、复制和容错能力,这使得它成为大规模消息处理应用程序的一个很好的解决方案。
在我们的经验中,消息传递的使用通常是相对低吞吐量的,但是可能需要较低的端到端延迟,并且通常依赖于Kafka提供的强大持久性保证。
在这个领域,Kafka可与ActiveMQ或RabbitMQ等传统消息传递系统相比较。
Kafka最初的用例是能够将用户活动跟踪管道重构为一组实时发布-订阅提要。这意味着将站点活动(页面视图、搜索或用户可能采取的其他操作)发布到中心主题,每个活动类型有一个主题。这些提要可用于订阅一系列用例,包括实时处理、实时监视和加载到Hadoop或以进行离线处理和报告的离线数据仓库系统。
由于为每个用户页面视图生成了许多活动消息,因此活动跟踪通常非常大。
Kafka通常用于操作监控数据。这包括聚合来自分布式应用程序的统计信息,以生成操作数据的集中提要。
许多人使用Kafka作为日志聚合解决方案的替代品。日志聚合通常从服务器收集物理日志文件,并将它们放在中心位置(可能是文件服务器或HDFS)进行处理。Kafka抽象了文件的细节,并将日志或事件数据作为消息流进行了更清晰的抽象。这允许较低的延迟处理,更容易支持多个数据源和分布式数据消费。与Scribe或Flume等以日志为中心的系统相比,Kafka提供了同样好的性能、由于复制而提供的更强的持久性保证以及更低的端到端延迟。
Kafka的许多用户在由多个阶段组成的处理管道中处理数据,从Kafka主题中消费原始输入数据,然后聚合、丰富或以其他方式转换为新的主题,以便进一步消费或后续处理。例如,用于推荐新闻文章的处理管道可以从RSS提要中抓取文章内容并将其发布到“articles”主题;进一步处理可将此内容规范化或删除,并将已清理的文章内容发布到新主题;最后一个处理阶段可能尝试向用户推荐这些内容。这样的处理管道根据各个主题创建实时数据流的图形。从0.10.0.0开始,ApacheKafka提供了一个称为Kafka Streams的轻量级但功能强大的流处理库来执行上述数据处理。除了Kafka流之外,其他开源流处理工具还包括Apache Storm 和 Apache Samza。
事件源是一种应用程序设计风格,其中状态更改记录为按时间顺序排列的记录序列。Kafka对非常大的存储日志数据的支持使其成为以这种风格构建的应用程序的优秀后端。
Kafka可以作为分布式系统的一种外部提交日志。日志有助于在节点之间复制数据,并充当失败节点恢复数据的重新同步机制。Kafka中的日志压缩--log compaction 特性有助于支持这种用法。在这种用法中,Kafka类似于Apache BookKeeper 项目。
1.3 Quick Start
本教程假设您正在重新开始,并且没有现有的Kafka或ZooKeeper数据。由于Kafka控制台脚本对于基于unix和Windows平台是不同的,所以在Windows平台上使用bin\windows\
而不是bin/
, 并将脚本扩展名更改为 .bat。
Download the 2.2.0 release and un-tar it.
>
tar
-xzf kafka_2.11-2.1.0.tgz
>
cd
kafka_2.11-2.1.0
Kafka使用 ZooKeeper ,所以如果还没有ZooKeeper服务器,需要先启动它。您可以使用kafka打包的方便脚本来获得一个快速且脏的单节点ZooKeeper实例。
> bin
/zookeeper-server-start
.sh config
/zookeeper
.properties
[2013-04-22 15:01:37,495] INFO Reading configuration from: config/zookeeper.properties (org.apache.zookeeper.server.quorum.QuorumPeerConfig)
- ...
现在启动Kafka服务器:
> bin
/kafka-server-start
.sh config
/server
.properties
- [2013-04-22 15:01:47,028] INFO Verifying properties (kafka.utils.VerifiableProperties)
- [2013-04-22 15:01:47,051] INFO Property socket.send.buffer.bytes is overridden to 1048576 (kafka.utils.VerifiableProperties)
- ...
让我们创建一个 只有一个分区和一个副本的 名为“test”的主题:
> bin
/kafka-topics
.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic
test
如果运行列出主题命令,现在可以看到这个主题:
> bin
/kafka-topics
.sh --list --zookeeper localhost:2181
- test
此外,您还可以配置代理(brokers),使其在发布不存在的主题时自动创建主题,而不是手动创建主题。
Kafka附带了一个命令行客户机,它将从文件或标准输入中获取输入,并将其作为消息发送到Kafka集群。默认情况下,每行将作为单独的消息发送。
运行生产者,然后在控制台中键入一些消息以发送到服务器。
> bin
/kafka-console-producer
.sh --broker-list localhost:9092 --topic
test
- This is a message
- This is another message
Kafka还有一个命令行消费者,它将把消息转储到标准输出。
> bin
/kafka-console-consumer
.sh --bootstrap-server localhost:9092 --topic
test
--from-beginning
- This is a message
- This is another message
如果您在不同的终端中运行了上面的每个命令,那么现在您应该能够在生产者终端中输入消息,并看到它们出现在消费者终端中。
所有命令行工具都有其他选项;在不带参数的情况下运行命令将显示更多详细的用法信息。
Step 6: Setting up a multi-broker cluster
到目前为止,我们只与一个经纪人--broker打交道,但这并不有趣。对于Kafka,单个代理只是一个大小为1的集群,因此除了启动多个代理实例外,没有什么大的变化。但是为了更好地理解它,让我们将集群扩展到三个节点(仍然都在本地机器上)。
首先,我们为每个代理创建一个配置文件(在Windows上使用copy命令):
>
cp
config
/server
.properties config
/server-1
.properties
>
cp
config
/server
.properties config
/server-2
.properties
现在编辑这些新文件并设置以下属性:
- config/server-1.properties:
- broker.id=1
- listeners=PLAINTEXT://:9093
- log.dirs=/tmp/kafka-logs-1
- config/server-2.properties:
- broker.id=2
- listeners=PLAINTEXT://:9094
- log.dirs=/tmp/kafka-logs-2
属性是集群中每个节点的唯一和永久名称。我们必须覆盖端口和日志目录,这仅仅是因为我们在同一台机器上运行这些目录,并且我们希望防止代理都试图在同一端口上注册或覆盖彼此的数据。
我们已经启动了ZooKeeper和我们的单节点,所以我们只需要启动两个新节点:
> bin
/kafka-server-start
.sh config
/server-1
.properties &
- ...
bin
/kafka-server-start
.sh config
/server-2
.properties &
- ...
现在创建一个复制因子为3的新主题:
> bin
/kafka-topics
.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic
好吧,但是现在我们有了一个集群,我们怎么知道哪个经纪人在做什么呢?要查看运行“描述主题”命令:
> bin
/kafka-topics
.sh --describe --zookeeper localhost:2181 --topic my-replicated-topic
- Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
- Topic: my-replicated-topic Partition: 0 Leader: 1 Replicas: 1,0,2 Isr: 1,0,2
下面是输出的解释。第一行给出了所有分区的摘要,每一行给出了关于一个分区的信息。因为这个主题只有一个分区,所以只有一行。
- “leader”是 负责 给定分区的所有读写 的节点(例如,本例中的分区0,leader是节点1--broker 1)。每个节点都将是分区中随机选择的一部分的领导者。
- “replicas”是复制这个分区日志的节点列表,不管它们是否是leader或甚至当前是否处于活动状态。
- “isr”是一组“同步”副本。这是 当前处于活动状态并被leader捕获的 副本列表的一个子集。
注意,在我的示例中,节点1是主题的唯一分区的leader。
我们可以对创建的原始主题运行相同的命令,以查看它在哪里:
> bin
/kafka-topics
.sh --describe --zookeeper localhost:2181 --topic
test
topic:test PartitionCount:1 ReplicationFactor:1 Configs:
- Topic: test Partition: 0 Leader: 0 Replicas: 0 Isr: 0
因此,这并不奇怪——原始主题没有副本,并且位于server 0上,这是我们创建集群时惟一的服务器。
让我们发布一些消息到我们的新主题:
> bin
/kafka-console-producer
.sh --broker-list localhost:9092 --topic my-replicated-topic
- ...
my
test
message 1
my
test
message 2
现在让我们消费这些消息:
> bin
/kafka-console-consumer
.sh --bootstrap-server localhost:9092 --from-beginning --topic my-replicated-topic
- ...
my
test
message 1
my
test
message 2
现在让我们测试一下容错性。经纪人1是领导者,所以让我们杀了它:
>
ps
aux |
grep
server-1.properties
root 11647 2.9 10.3 4739040 156944 pts/1 Sl+ 13:33 1:39 /opt/modules/jdk1.8.0_172/bin/java ...
kill
-9 11647
在Windows上使用:
> wmic process where
"caption = 'java.exe' and commandline like '%server-1.properties%'"
get processid
- ProcessId
- 6016
> taskkill
/pid
6016
/f
领导层已切换到其中一个从属服务器,节点1不再位于同步副本集中:
> bin
/kafka-topics
.sh --describe --zookeeper localhost:2181 --topic my-replicated-topic
- Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
- Topic: my-replicated-topic Partition: 0 Leader: 0 Replicas: 1,0,2 Isr: 0,2
但是这些消息仍然可以被消费,即使最初记录这些内容的领导者已经下台了:
> bin
/kafka-console-consumer
.sh --bootstrap-server localhost:9092 --from-beginning --topic my-replicated-topic
- ...
my
test
message 1
my
test
message 2
Step 7: Use Kafka Connect to import/export data
从控制台写入数据并将其写入控制台是一个方便的起点,但是您可能希望使用其他来源的数据或将Kafka的数据导出到其他系统。对于许多系统,您可以使用Kafka Connect导入或导出数据,而不是编写定制的集成代码。
Kafka Connect是Kafka附带的一个 用于将数据导入和导出到Kafka 的工具。它是一个运行连接器的可扩展工具,连接器实现了与外部系统交互的自定义逻辑。在这个快速入门中,我们将看到如何使用简单的连接器运行Kafka Connect,这些连接器将数据从文件导入Kafka主题,并将数据从Kafka主题导出到文件。
首先,我们将从创建一些种子数据开始测试:
>
echo
-e
"foo\nbar"
>
test
.txt
或在Windows上:
>
echo
foo>
test
.txt
>
echo
bar>>
test
.txt
接下来,我们将启动两个以独立-- standalone 模式运行的连接器,这意味着它们运行在单个本地专用进程中。我们提供了三个配置文件作为参数。第一种始终是Kafka Connect进程的配置,包括要连接的常见配置,如要连接的Kafka代理 和 数据的序列化格式。其余的配置文件每个都指定一个要创建的连接器。这些文件包括一个惟一的连接器名称、要实例化的连接器类以及连接器所需的任何其他配置。
> bin
/connect-standalone
.sh config
/connect-standalone
.properties config
/connect-file-source
.properties config
/connect-file-sink
.properties
这些示例配置文件(包含在Kafka中)使用您之前启动的默认本地集群配置并创建两个连接器:第一个是源连接器,它从输入文件读取行并生成每个行到Kafka主题;第二个是接收器连接器,它从Kafka主题读取消息,并在输出文件中生成每个行。
在启动期间,您将看到许多日志消息,包括一些指示连接器正在实例化的消息。Kafka连接进程启动后,源连接器应该开始从读取行,并将它们生成到主题
,而接收器连接器应该开始从主题
读取消息,并将它们写入文件
。我们可以通过检查输出文件的内容来验证数据是否已经通过整个管道传递:
>
more
test
.sink.txt
- foo
- bar
注意数据存储在Kafka主题中,所以我们也可以运行控制台消费者来查看主题中的数据(或者使用自定义消费者代码来处理):
连接器继续处理数据,因此我们可以将数据添加到文件中,并看到它在管道中移动:
>
echo
Another line>>
test
.txt
您应该看到该行出现在控制台消费者输出和接收器文件中。
Step 8: Use Kafka Streams to process data
Kafka Streams是一个客户端库,用于构建关键任务的实时应用程序和微服务,其中的输入和/或输出数据存储在Kafka集群中。Kafka Streams结合了在客户端编写和部署标准Java和Scala应用程序的简单性,以及Kafka服务器端集群技术的优点,使这些应用程序具有高度可伸缩性、弹性、容错性、分布式等特性。这个快速入门示例将演示如何运行在这个库中编码的流应用程序。
1.4 Ecosystem(生态系统)
在主要发行版之外,有很多与Kafka集成的工具。生态系统页面列出了其中许多,包括流处理系统、Hadoop集成、监视和部署工具。
1.5 Upgrading From Previous Versions
Upgrading from 0.8.x, 0.9.x, 0.10.0.x, 0.10.1.x, 0.10.2.x, 0.11.0.x, 1.0.x, 1.1.x, or 2.0.0 to 2.1.0
请注意,2.1.x包含对用于存储消费者偏移量的内部模式的更改。升级完成后,将无法降级到以前的版本。有关详细信息,请参阅下面的滚动升级说明。
对于滚动升级:
- 更新所有brokers上的server.properties并添加以下属性。CURRENT_KAFKA_VERSION是指您要从中升级的版本。CURRENT_MESSAGE_FORMAT_VERSION是指当前使用的消息格式版本。如果以前重写了消息格式版本,则应保留其当前值。或者,如果您要从0.11.0.x之前的版本升级,则CURRENT_MESSAGE_FORMAT_VERSION 应该设置为与CURRENT_KAFKA_VERSION匹配。
- inter.broker.protocol.version=CURRENT_KAFKA_VERSION(e.g. 0.8.2, 0.9.0, 0.10.0, 0.10.1, 0.10.2, 0.11.0, 1.0, 1.1)
- log.message.format.version=CURRENT_MESSAGE_FORMAT_VERSION(有关此配置的详细信息,请参阅升级后的潜在性能影响-- potential performance impact following the upgrade 。)
如果您要从0.11.0.x、1.0.x、1.1.x或2.0.x升级,但尚未覆盖消息格式,则只需覆盖代理间协议版本。
。inter.broker.protocol.version=CURRENT_KAFKA_VERSION (0.11.0, 1.0, 1.1, 2.0).
2. 一次升级一个代理:关闭代理,更新代码,并重新启动它。这样做之后,代理将运行最新版本,您可以验证集群的行为和性能是否符合预期。如果出现任何问题,目前仍有可能降级。
3. 一旦集群的行为和性能得到验证,通过编辑并将其设置为2.1来提升协议版本。
4. 逐个重新启动代理程序以使新协议版本生效。一旦代理开始使用最新的协议版本,就不能再将集群降级到较旧的版本。
5. 如果您已经按照上面的指示重写了消息格式版本,那么您需要再进行一次滚动重启,以便将其升级到最新版本。一旦所有(或大部分)消费者都升级到0.11.0或更高版本,在每个代理的版本上把log.message.format改为2.1,并逐个重新启动它们。注意,不再维护的旧Scala客户机不支持0.11中引入的消息格式,因此为了避免转换成本(或者正好利用正好一次语义),必须使用新的Java客户机。
其它升级说明:
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
2. APIS
Kafka包括五个核心APIs:
- The Producer API--生产者API 允许应用程序将数据流发送到Kafka集群中的主题。
- The Consumer API--消费者API 允许应用程序从Kafka集群中的主题读取数据流。
- The Streams API--流API 允许将数据流从输入主题转换为输出主题。
- The Connect API--连接API 允许实现 把数据 从某个源系统或应用程序持续拉入Kafka或从Kafka推入某些接收器系统或应用程序的连接器。
- The AdminClient API--管理员客户端API 允许管理和检查主题、代理和其他Kafka对象。
Kafka通过一个独立于语言的协议公开了它的所有功能,该协议的客户端可以在许多编程语言中使用。然而,只有Java客户端作为主Kafka项目的一部分被维护,其他客户端可以作为独立的开源项目来使用。 here:https://cwiki.apache.org/confluence/display/KAFKA/Clients有一个非Java客户端列表。
2.1 Producer API
生产者API允许应用程序将数据流发送到Kafka集群中的主题。
javadocs中给出了演示如何使用生产者的示例。
要使用生产者,可以使用以下Maven依赖项:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.1.0</version>
</dependency>
2.2 Consumer API
消费者API允许应用程序从Kafka集群中的主题读取数据流。
javadocs中给出了演示如何使用消费者的示例。
要使用消费者,可以使用以下Maven依赖项:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.1.0</version>
</dependency>
2.3 Streams API
流API允许将数据流从输入主题转换为输出主题。
javadocs:http://kafka.apache.org/21/javadoc/index.html?org/apache/kafka/streams/KafkaStreams.html中给出了演示如何使用此库的示例。
有关使用streams API的其他文档可在 here:http://kafka.apache.org/21/documentation/streams获得。
要使用Kafka流,可以使用以下Maven依赖项:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
<version>2.1.0</version>
</dependency>
在使用Scala时,您可以选择包含库。有关使用Kafka Streams DSL for Scala的其他文档可以在开发人员指南-- in the developer guide:http://kafka.apache.org/21/documentation/streams/developer-guide/dsl-api.html#scala-dsl中找到。
要将kafka streams DSL用于scala 2.11,可以使用以下Maven依赖项:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams-scala_2.11</artifactId>
<version>2.1.0</version>
</dependency>
2.4 Connect API
ConnectAPI允许实现 数据 从某些源数据系统持续拉入Kafka或从Kafka推入某些接收器数据系统的连接器。
不过,Connect的许多用户不需要直接使用这个API,他们可以使用预构建的连接器,而不需要编写任何代码。有关使用Connect的其他信息可以在 here:http://kafka.apache.org/documentation.html#connect找到。
2.5 AdminClient API
AdminClient API支持管理和检查主题、代理、acls和其它Kafka对象。
要使用AdminClient API,请添加以下Maven依赖项:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.1.0</version>
</dependency>
有关AdminClient API的更多信息,请参阅 javadoc。
3. CONFIGURATION
Kafka使用 property file format 中的键值对进行配置。这些值可以从文件中提供,也可以通过编程方式提供。
3.1 Broker Configs
基本配置如下:
面将更详细地讨论主题级配置和默认值。
NAME | DESCRIPTION | TYPE | DEFAULT | VALID VALUES | IMPORTANCE | DYNAMIC UPDATE MODE | ||
zookeeper.connect | 以![]() ![]() ![]() | string | high | read-only | ||||
advertised.listeners | 如果 listeners 的配置属性不同,监听器将发布到ZooKeeper供客户端使用。在IaaS环境中,这可能需要不同于代理--broker绑定到的接口。如果未设置,则将使用 listeners 的值。与 listeners 不同,声明0.0.0.0元地址是无效的。 | string | null | high | per-broker | |||
auto.create.topics.enable | 启用在服务上自动创建主题 | boolean | true | high | read-only | |||
auto.leader.rebalance.enable | 启用自动leader平衡。如果需要,后台线程定期检查并触发leader balance。 | boolean | true | high | read-only | |||
background.threads | 用于各种后台处理任务的线程数 | int | 10 | [1,...] | high | cluster-wide | ||
broker.id | 此服务器的broker id。如果未设置,将生成一个惟一的broker id。为了避免zookeeper生成的broker id和用户配置的broker id之间的冲突,生成的broker id从reserve .broker.max.id + 1 开始。 | int | -1 | high | read-only | |||
compression.type | 指定给定主题的最终压缩类型。此配置接受标准压缩编解码器(“gzip”, “snappy”, “lz4”, “zstd”)。它还接受“uncompressed”,这相当于没有压缩;和“producer”,这意味着保留生产者设置的原始压缩编解码器。 | string | producer | high | cluster-wide | |||
delete.topic.enable | 启用删除主题。如果关闭此配置,则通过管理工具删除主题将不起作用。 | boolean | true | high | read-only | |||
leader.imbalance.check.interval.seconds | 控制器触发分区重新平衡检查的频率 | long | 300 | high | read-only | |||
leader.imbalance.per.broker.percentage | 每个broker允许的leader不平衡比率。如果控制器超过每个broker的这个值,它将触发一个leader平衡。该值以百分比形式指定 | int | 10 | high | read-only | |||
listeners | Listener List(监听器列表)--我们 将监听的URIs 和 监听器名称 的逗号分隔列表。如果侦听器名称不是安全协议,则还必须设置listener.security.protocol.map。将主机名指定为0.0.0.0以绑定到所有接口。保留主机名为空以绑定到默认接口。合法侦听器列表示例: PLAINTEXT://myhost:9092, SSL://:9091, CLIENT://0.0.0.0:9092, REPLICATION://localhost:9093 | string | null | high | per-broker | |||
log.dir | 保存日志数据的目录(log.dirs属性的补充) | string | /tmp/kafka-logs | high | read-only | |||
log.dirs | 保存日志数据的目录。如果未设置,则使用log.dir中的值 | string | null | high | read-only | |||
log.flush.interval.messages | 在将消息刷新到磁盘之前,日志分区上累积的消息数 | long | 9223372036854775807 | [1,...] | high | cluster-wide | ||
| 在刷新到磁盘之前,任何主题中的消息保存在内存中的最长时间(毫秒)。如果未设置,则使用log.flush.scheduler.interval.ms中的值 | int | null | high | read-only | |||
log.flush.offset.checkpoint.interval.ms | 更新作为日志恢复点的上次刷新的持久记录的频率 | int | 60000 | [0,...] | high | read-only | ||
log.retention.bytes | 删除日志前日志的最大大小 | long | -1 | high | cluster-wide | |||
log.retention.hours | 删除日志文件之前保留日志文件的小时数(小时),第三级(即优先级)于log.retention.ms 属性 | int | 168 | high | read-only | |||
log.retention.minutes | 删除日志文件之前保留日志文件的分钟数(以分钟为单位),仅次于log.retention.ms属性。如果未设置,则使用log.retention.hours中的值 | int | null | high | read-only | |||
log.retention.ms | 删除日志文件之前保留日志文件的毫秒数(以毫秒为单位),如果未设置,则使用log.retention.minutes中的值。 | long | null | high | read-only | |||
log.roll.hours | 新日志段推出前的最长时间(小时),仅次于log.roll.ms属性 | int | 168 | [1,...] | high | read-only | ||
log.roll.jitter.hours | 要从logRollTimeMillis(小时)中减去的最大抖动,仅次于log.roll.jitter.ms属性 | int | 0 | [0,...] | high | read-only | ||
log.roll.jitter.ms | 要从logRollTimeMillis(毫秒)中减去的最大抖动。如果未设置,则使用log.roll.jitter.hours中的值 | long | null | high | cluster-wide | |||
log.roll.ms | 新日志段展开前的最长时间(毫秒)。如果未设置,则使用log.roll.hours中的值 | long | null | high | cluster-wide | |||
log.segment.bytes | 单个日志文件的最大大小 | int | 1073741824 | [14,...] | high | cluster-wide | ||
log.segment.delete.delay.ms | 从文件系统中删除文件之前等待的时间量 | long | 60000 | [0,...] | high | cluster-wide | ||
message.max.bytes | Kafka允许的最大记录批大小。如果此值增加,并且存在大于0.10.2的消费者,则还必须增加消费者的获取大小,以便他们能够获取如此大的记录批。 在最新的消息格式版本中,为了提高效率,记录总是分组成批。在以前的消息格式版本中,未压缩的记录不分组为批,在这种情况下,此限制仅适用于单个记录。 可以使用主题级别max.message.bytes 配置对每个主题进行设置。 | int | 1000012 | [0,...] | high | cluster-wide | ||
min.insync.replicas | 当生产者将acks设置为“all”(或“-1”)时,min.insync.replica指定必须确认写入成功的最小副本数量。如果不能满足这个最小值,那么生产者将引发一个异常(NotEnoughReplicas或NotEnoughReplicasAfterAppend)。 在一起使用时,min.insync.replicas和acks允许您强制执行更高的持久性保证。典型的场景是创建一个复制因子为3的主题,将min.insync.replicas设置为2,并使用acks 为all 生成。这将确保生产者在大多数副本没有收到写操作时引发异常。 | int | 1 | [1,...] | high | cluster-wide | ||
num.io.threads | 服务器用于处理请求(其中可能包括磁盘I/O)的线程数。 | int | 8 | [1,...] | high | cluster-wide | ||
num.network.threads | 服务器用于接收来自网络的请求并向此网络发送响应的线程数 | int | 3 | [1,...] | high | cluster-wide | ||
num.recovery.threads.per.data.dir | 在启动时用于日志恢复和在关闭时用于刷新 的每个数据目录的线程数 | int | 1 | [1,...] | high | cluster-wide | ||
num.replica.alter.log.dirs.threads | 可以在日志目录之间移动副本的线程数,其中可能包括磁盘I/O | int | null | high | read-only | |||
num.replica.fetchers | 用于从一个源broker复制消息的提取--fetcher线程数。增加这个值可以提高跟随器代理中的I/O并行度。 | int | 1 | high | cluster-wide | |||
offset.metadata.max.bytes | 与 偏移量提交 关联 的元数据项的最大大小 | int | 4096 | high | read-only | |||
offsets.commit.required.acks | 接受提交之前所需的acks。通常,不应该重写默认值(-1) | short | -1 | high | read-only | |||
offsets.commit.timeout.ms | 偏移量提交将被延迟,直到偏移量主题的所有副本收到提交或达到此超时。这类似于生产者请求超时。 | int | 5000 | [1,...] | high | read-only | ||
offsets.load.buffer.size | 将偏移量加载到缓存时用于从偏移量段读取的批处理大小(软限制,如果记录太大则重写)。 | int | 5242880 | [1,...] | high | read-only | ||
offsets.retention.check.interval.ms | 检查陈旧偏移量的频率 | long | 600000 | [1,...] | high | read-only | ||
offsets.retention.minutes | 当一个消费者群体失去所有的消费者(即成为空的消费者)后,它的偏移量将在被丢弃之前保留一段时间。对于独立的消费者(使用手动分配),偏移量将在最后一次提交的时间加上此保留期之后过期。 | int | 10080 | [1,...] | high | read-only | ||
offsets.topic.compression.codec | 偏移量主题的压缩编解码器——压缩可用于实现“原子”提交 | int | 0 | high | read-only | |||
offsets.topic.num.partitions | 偏移量提交主题 的分区数(部署后不应更改) | int | 50 | [1,...] | high | read-only | ||
offsets.topic.replication.factor | 偏移量主题的复制因子(设置得更高以确保可用性)。在群集大小满足此复制因子要求之前,内部主题创建将失败。 | short | 3 | [1,...] | high | read-only | ||
offsets.topic.segment.bytes | 偏移量主题段字节应该保持相对较小,以便更快地进行日志压缩和缓存加载 | int | 104857600 | [1,...] | high | read-only | ||
queued.max.requests | 阻塞网络线程之前允许的排队请求数 | int | 500 | [1,...] | high | read-only | ||
replica.fetch.min.bytes | 每个获取响应所需的最小字节数。如果没有足够的字节,则等待replicaMaxWaitTimeMs | int | 1 | high | read-only | |||
replica.fetch.wait.max.ms | follower副本发出的每个获取器(fetcher)请求的最大等待时间。该值应始终小于replica.lag.time.max.ms,以防止低吞吐量主题的ISR频繁收缩。 | long | 500 | high | read-only | |||
replica.high.watermark.checkpoint.interval.ms | 将高水印保存到磁盘上的频率 | long | 5000 | high | read-only | |||
replica.lag.time.max.ms | 如果跟随者-fllower没有发送任何获取请求,或者至少在这个时候还没有消耗到领导者-leader的日志结束偏移量,领导者将把此跟随者从isr中删除。 | long | 10000 | high | read-only | |||
replica.socket.receive.buffer.bytes | 网络请求的套接字接收缓冲区 | int | 65536 | high | read-only | |||
replica.socket.timeout.ms | 网络请求的套接字超时。其值至少应为replica.fetch.wait.max.ms | int | 30000 | high | read-only | |||
request.timeout.ms | 此配置控制客户端等待请求响应的最长时间。如果在超时时间结束之前没有收到响应,则客户端将在必要时重新发送请求,或者在重试次数用完时使请求失败。 | int | 30000 | high | read-only | |||
socket.receive.buffer.bytes | 套接字服务器套接字的SO_RCVBUF缓冲区。如果值为-1,则使用OS缺省值(即默认值)。 | int | 102400 | high | read-only | |||
socket.request.max.bytes | 套接字请求中的最大字节数 | int | 104857600 | [1,...] | high | read-only | ||
socket.send.buffer.bytes | 套接字服务器套接字的SO_SNDBUF缓冲区。如果值为-1,则使用OS缺省值。 | int | 102400 | high | read-only | |||
transaction.max.timeout.ms | 事务允许的最大超时。如果客户端请求的事务时间超过此时间,那么代理将在initPoducerIRequest中返回错误。这样可以防止客户机超时过大,从而阻止客户机读取事务中包含的主题。 | int | 900000 | [1,...] | high | read-only | ||
transaction.state.log.load.buffer.size | 当将生产者ids和事务加载到缓存中时,用于从事务日志段读取的批处理大小(软限制,如果记录太大则重写)。 | int | 5242880 | [1,...] | high | read-only | ||
transaction.state.log.min.isr | 覆盖事物主题的min.insync.replicas 配置 | int | 2 | [1,...] | high | read-only | ||
transaction.state.log.num.partitions | 事务主题的分区数(部署后不应更改)。 | int | 50 | [1,...] | high | read-only | ||
transaction.state.log.replication.factor | 事务主题的复制因子(设置得更高以确保可用性)。在群集大小满足此复制因子要求之前,内部主题创建将失败。 | short | 3 | [1,...] | high | read-only | ||
transaction.state.log.segment.bytes | 事务主题段字节应该保持相对较小,以便更快地压缩日志和加载缓存。 | int | 104857600 | [1,...] | hight | read-only | ||
transactional.id.expiration.ms | 事务协调器在不接收任何事务状态更新的情况下,主动使生产者事务ID到期之前等待的最长时间(毫秒)。 | int | 604800000 | [1,...] | high | read-only | ||
unclean.leader.election.enable | 指示是否允许不在ISR集中的副本被选为最后的领导者,即使这样做可能导致数据丢失 | boolean | false | high | cluster-wide | |||
zookeeper.connection.timeout.ms | 客户端等待与ZooKeeper建立连接的最长时间。如果未设置,则使用zookeeper.session.timeout.ms中的值 | int | null | high | read-only | |||
zookeeper.max.in.flight.requests | 客户端在阻塞前 将发送给ZooKeeper的未确认请求 的最大数目。 | int | 10 | [1,...] | high | read-only | ||
zookeeper.session.timeout.ms | Zookeeper会话超时时间 | int | 6000 | high | read-only | |||
zookeeper.set.acl | 将客户端设置为使用安全ACLs | boolean | false | high | read-only | |||
borker-rack | 经纪人的机架。这将在机架感知复制分配中用于容错。例子:“RACK1”、“us-east-1d” | string | null | medium | read-only | |||
connections.max.idle.ms | 空闲连接超时:服务器套接字处理器线程关闭空闲时间超过此值的连接 | long | 600000 | medium | read-only | |||
controlled.shutdown.enable | 启用服务器的受控关闭 | boolean | true | mediun | read-only | |||
controlled.shutdown.max.retries | 受控停机可能由于多种原因而失败。这决定发生此类故障时的重试次数。 | int | 3 | medium | read-only | |||
controlled.shutdown.retry.backoff.ms | 在每次重试之前,系统需要时间从导致上一次失败的状态(控制器故障转移、副本延迟等)中恢复。此配置决定重试前等待的时间。 | long | 5000 | medium | read-only | |||
controller.socket.timeout.ms | 控制器到代理通道的套接字超时 | int | 30000 | medium | read-only | |||
default.replication.factor | 自动创建主题的默认复制因子 | int | 1 | medium | read-only | |||
delegation.token.expiry.time.ms | 用于生成和验证委托令牌的主/密钥。必须在所有代理中配置相同的密钥。如果密钥未设置或设置为空字符串,代理将禁用委派令牌支持。 | password | null |
| read-only | |||
delegation.token.max.lifetime.ms | 令牌有一个最长的生存期,超过该生存期将无法再续订。默认值7天。 | long | 604800000 | [1,...] | medium | read-only | ||
delete.records.purgatory.purge.interval.requests | 删除记录请求清除的清除间隔(请求数) | int | 1 | medium | read-only | |||
fetch.purgatory.purge.interval.requests | 提取请求净化室的净化间隔(请求数) | int | 1000 | medium | read-only | |||
group.initial.rebalance.delay.ms | 在执行第一次重新平衡之前,组协调器将等待更多消费者加入新组的时间。较长的延迟意味着可能较少的重新平衡,但是增加了处理开始之前的时间。 | int | 3000 | medium | read-only | |||
group.max.session.timeout.ms | 已注册消费者的最大允许会话超时。超时时间越长,消费者在两次心跳之间处理消息的时间就越多,代价是检测故障的时间就越长。 | int | 300000 | medium | read-only | |||
group.min.session.timeout.ms | 已注册消费者的最小允许会话超时。较短的超时导致更快的故障检测,代价是更频繁的消费者心跳,这可能会耗尽代理资源。 | int | 6000 | medium | read-only | |||
inter.broker.listener.name | 用于代理之间通信的侦听器的名称。如果未设置,则侦听器名称由security.inter.broker.protocol定义。同时设置此属性和security.inter.broker.protocol属性是错误的。 | string | null | medium | read-only | |||
inter.broker.protocol.version | 指定将使用哪个版本的代理间协议。在所有代理升级到新版本后,这通常会被提高。一些有效值的示例有:0.8.0,0.8.1,e.8.1.1、0.8.2、0.8.2.0、0.8.2.1、0.9.0.0、0.9.0.1请检查完整列表的ApiVersion | string | 2.1-IV2 | kafka.api.ApiVersionValidator$@4eb7f003 | medium | read-only | ||
log.cleaner.backoff.ms | 没有要清理的日志时的睡眠时间量/。。 | long | 15000 | [0,...] | medium | cluster-wide | ||
log.cleaner.dedupe.buffer.size | 用于跨所有清理线程执行日志重复数据消除的总内存 | long | 134217728 | medium | cluster-wide | |||
log.cleaner.delete.retention.ms | 删除记录保留多长时间? | long | 86400000 | medium | cluster-wide | |||
log.cleaner.enable | 启用日志清理程序进程以在服务器上运行。如果使用带有cleanup.policy=compact的任何主题(包括内部偏移量主题),则应启用。如果禁用,这些主题将不会压缩并不断增长 | boolean | true | medium | read-only | |||
log.cleaner.io.buffer.load.factor | 日志清除器重复数据消除缓冲区负载系数。重复数据消除缓冲区的满百分比。较高的值将允许一次清理更多的日志,但会导致更多的哈希冲突。 | double | 0.9 | medium | cluster-wide | |||
log.cleaner.io.buffer.size | 在所有清理器线程中用于日志清理器I/O缓冲区的总内存 | int | 524288 | [0,...] | medium | cluster-wide | ||
log.cleaner.io.max.bytes.per.second | 日志清洗器将受到限制,以便其读写I/O之和平均小于此值。 | double | 1.7976931348623157E308 | medium | cluster-wide | |||
log.cleaner.min.cleanable.ratio | 可清理日志的脏日志与总日志的最小比率 | double | 0.5 | medium | cluster-wide | |||
log.cleaner.min.compaction.lag.ms | 消息在日志中保持未压缩的最小时间。仅适用于正在压缩的日志。 | long | 0 | medium | cluster-wide | |||
log.cleaner.threads | 用于日志清理的后台线程数 | int | 1 | [0,...] | medium | cluster-wide | ||
log.cleanup.policy | 保留窗口以外的段的默认清理策略。有效策略的逗号分隔列表。有效的策略是: "delete" 和 "compact" | list | delete | [compact, delete] | medium | cluster-wide | ||
log.index.interval.bytes | 在偏移索引中添加条目的间隔 | int | 4096 | [0,...] | medium | cluster-wide | ||
log.index.size.max.bytes | 偏移量索引的最大大小(以字节为单位) | int | 10485760 | [4,...] | medium | cluster-wide | ||
log.message.format.version | 定代理将用于向日志追加消息的消息格式版本。该值应该是一个有效的ApiVersion。一些示例是:0.8.2, 0.9.0.0, 0.10.0,请检查ApiVersion以获得更多详细信息。通过设置特定的消息格式版本,用户可以验证磁盘上所有现有的消息都小于或等于指定的版本。不正确地设置此值将导致使用旧版本的消费者中断,因为他们将接收到格式不理解的消息。 | string | 2.1-IV2 | kafka.api.ApiVersionValidator$@4eb7f003 | medium | cluster-wide | ||
log.message.timestamp.difference.max.ms | 代理接收消息时的时间戳与消息中指定的时间戳之间允许的最大差异。如果log.message.timestamp.type=CreateTime,如果时间戳的差异超过此阈值,则将拒绝消息。如果log.message.timestamp.type=LogAppendTime,则忽略此配置。允许的最大时间戳差异不应大于log.retention.ms,以避免不必要的频繁日志滚动。 | long | 9223372036854775807 | medium | cluster-wide | |||
log.message.timestamp.type | 定义消息中的时间戳是消息创建时间还是日志附加时间。值应为`CreateTime` 或`LogAppendTime` | string | CreateTime | [CreateTime, LogAppendTime] | medium | cluster-wide | ||
| 创建新段时是否应预分配文件?如果您在Windows上使用Kafka,可能需要将其设置为true。 | boolean | false | medium | cluster-wide | |||
log.retention.check.interval.ms | 日志清理器检查日志是否符合删除条件的频率(以毫秒为单位) | long | 300000 | [1,...] | medium | read-only | ||
max.connections.per.ip.overrides | 以逗号分隔的每个IP或主机名的列表将覆盖默认的最大连接数。示例值为“hostname:100127.0.0.1:200” | string | "" | medium | cluster-wide | |||
max.incremental.fetch.session.cache.slots | 我们将维护的增量获取会话的最大数量。 | int | 1000 | [0,...] | medium | read-only | ||
num.partitions | 每个主题的默认日志分区数 | int | 1 | [1,...] | medium | read-only | ||
password.encoder.old.secret | 用于对动态配置的密码进行编码的旧秘密。只有在更新秘密时才需要这样做。如果指定,则当代理启动时,所有动态编码的密码将使用此旧密码解码,并使用password.encoder.secret重新编码。 | password | null | medium | read-only | |||
password.encoder.secret | 用于编码此代理的动态配置密码的秘密。 | password | null | medium | read-only | |||
principal.builder.class | 实现KafkaPrincipalBuilder接口的类的完全限定名,该接口用于构建授权期间使用的KafkaPrincipal对象。此配置还支持已弃用的PrincipalBuilder接口,该接口以前用于通过SSL进行客户机身份验证。如果没有定义主体构建器,则默认行为取决于使用的安全协议。对于SSL身份验证,如果提供了主体名称,则主体名称将是与客户机证书相区别的名称;否则,如果不需要客户机身份验证,则主体名称将是匿名的。对于SASL身份验证,如果使用GSSAPI,则使用sasl .kerberos.principal.to.local.rules定义的规则派生主体,并使用其他机制的SASL身份验证ID。对于纯文本,主体将是匿名的。 | class | null | medium | per-broker | |||
producer.purgatory.purge.interval.requests | 生产者净化室的净化间隔(请求数) | int | 1000 | medium | read-only | |||
queued.max.request.bytes | 在不再读取请求之前允许的排队字节数 | long | -1 | medium | read-only | |||
replica.fetch.backoff.ms | 发生提取分区错误时的睡眠时间。 | int | 1000 | [0,...] | medium | read-only | ||
replica.fetch.max.bytes | 尝试为每个分区提取的消息字节数。这不是绝对最大值,如果提取的第一个非空分区中的第一个记录批大于此值,则仍将返回该记录批,以确保可以取得进展。代理接受的最大记录批处理大小是通过message.max.bytes(broker config)或max.message.bytes(topic config)定义的。 | int | 1048576 | [0,...] | medium | read-only | ||
replica.fetch.response.max.bytes | 整个提取响应所需的最大字节数。记录是批量获取的,如果获取的第一个非空分区中的第一个记录批大于此值,则仍将返回该记录批,以确保可以取得进展。因此,这不是绝对最大值。代理接受的最大记录批处理大小是通过message.max.bytes(broker config)或max.message.bytes(topic config)定义的。 | int | 10485760 | [0,...] | medium | read-only | ||
reserved.broker.max.id | 可用于broker.id的最大数目 | int | 1000 | [0,...] | medium | read-only | ||
sasl.client.callback.handler.class | 实现authenticatecallbackhandler接口的SASL(简单认证和安全层协议;简单验证和安全层 )客户端回调处理程序类的完全限定名。 | class | null | medium | read-only | |||
sasl.enabled.mechanisms | 在Kafka服务器中启用的SASL机制列表。该列表可以包含安全提供程序可用的任何机制。默认情况下仅启用GSSAPI。 | list | GSSAPI | medium | per-broker | |||
sasl.jaas.config | 用于SASL连接的JAAS登录上下文参数,格式为JAAS配置文件使用的格式。here描述了JAAS配置文件格式。值的格式为:"loginModuleClass controlFlag (optionName=optionValue)*;" 。对于经纪人,配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.jaas.config=com.example.ScramLoginModule 是必须的; | password | null | medium | per-broker | |||
sasl.kerberos.kinit.cmd | Kerberos kinit命令路径。 | string | /usr/bin/kinit | medium | per-broker | |||
sasl.kerberos.min.time.before.relogin | 登录线程刷新尝试之间的睡眠时间。 | long | 60000 | medium | per-broker | |||
sasl.kerberos.principal.to.local.rules | 从主体名称映射到短名称(通常是操作系统用户名)的规则列表。规则按顺序计算,第一个与主体名称匹配的规则用于将其映射到短名称。列表中的任何后面的规则都将被忽略。默认情况下,表单{username}/{hostname}@{REALM}的主体名称映射到{username}。有关格式的更多信息,请参见 security authorization and acls.注意,如果由principal.builder.class配置提供了KafkaPrincipalBuilder 扩展,则忽略此配置。 | list | DEFAULT | medium |
per-broker | |||
sasl.kerberos.service.name | 运行Kafka的kerberos主体名称。这可以在Kafka的JAAS 配置或Kafka的配置中定义。 | string | null | medium | per-broker | |||
sasl.kerberos.ticket.renew.jitter | 添加到续订时间的随机抖动百分比。 | double | 0.05 | medium | per-broker | |||
sasl.kerberos.ticket.renew.window.factor | 登录线程将休眠,直到达到从上一次刷新到票证到期的指定窗口时间系数,此时它将尝试续订票证。 | double | 0.8 | medium | per-broker | |||
sasl.login.callback.handler.class | 实现AuthenticateCallbackHandler接口的SASL登录回调处理程序类的完全限定名。对于代理程序,登录回调处理程序配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.login.callback.handler.class=com.example.CustomScramLoginCallbackHandler | class | null | medium | read-only | |||
sasl.login.class | 实现Login接口的类的完全限定名。对于代理,登录配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.login.class=com.example.customscramlogin | class | null | medium | read-only | |||
sasl.login.refresh.buffer.seconds | 刷新凭据时,凭据过期前要保持的缓冲时间(以秒为单位)。如果刷新时间比缓冲区秒数更接近到期时间,则将向上移动刷新时间,以尽可能多地保持缓冲区时间。 合法值介于0和3600(1小时)之间;如果未指定值,则使用默认值300(5分钟)。如果此值和sasl.login.refresh.min.period.seconds的总和超过凭据的剩余生存期,则它们都将被忽略。目前仅适用于OAUTHBEARER。 | short | 300 | medium | per-broker | |||
sasl.login.refresh.min.period.seconds |
| short | 60 | medium | per-broker | |||
sasl.login.refresh.window.factor | 登录刷新线程将休眠,直到达到与凭据生存期相关的指定窗口因子,此时它将尝试刷新凭据。法定值介于0.5(50%)和1.0(100%)之间(含0.5(50%)和1.0(100%),如果未指定值,则使用默认值0.8(80%)。目前仅适用于OAUTHBEARER。 | double | 0.8 | medium | per-broker | |||
sasl.login.refresh.window.jitter | 相对于添加到登录刷新线程睡眠时间的凭据生存期的最大随机抖动量。法定值介于0和0.25(含)之间;如果未指定值,则使用默认值0.05(5%)。目前仅适用于OAUTHBEARER。 | double | 0.05 | medium | per-broker | |||
sasl.mechanism.inter.broker.protocol | 用于代理间通信的SASL机制。默认值为 GSSAPI。 | string | GSSAPI | medium | per-broker | |||
sasl.server.callback.handler.class | 实现AuthenticateCallbackHandler接口的SASL服务器回调处理程序类的完全限定名。服务器回调处理程序必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.plain.sasl.server.callback.handler.class=com.example.customPlainCallbackhandler | class | null | medium | read-only | |||
security.inter.broker.protocol | 用于在代理之间通信的安全协议。有效值是: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL。同时设置此属性和inter.broker.listener.name属性是错误的。 | string | PLAINTEXT | medium | read-only | |||
ssl.cipher.suites | 密码套件的列表。这是身份验证、加密、MAC和密钥交换算法的命名组合,用于协商使用TLS或SSL网络协议的网络连接的安全设置。默认情况下,支持所有可用的密码套件。 | list | "" | medium | per-broker | |||
ssl.client.auth | 将Kafka代理配置为请求客户端身份验证。以下设置是常见的:
| string | none | [required, requested, none] | medium | per-broker | ||
ssl.enabled.protocols | 为SSL连接启用的协议列表。 | list | TLSv1.2,TLSv1.1,TLSv1 | medium | per-broker | |||
ssl.key.password | 密钥存储文件中私钥的密码。这对于客户是可选的。 | password | null | medium | per-broker | |||
ssl.keymanager.algorithm | 密钥管理器工厂用于SSL连接的算法。默认值是为Java虚拟机配置的密钥管理器工厂算法。 | string | SunX509 | medium | per-broker | |||
ssl.keystore.location | 密钥存储文件的位置。这对于客户端是可选的,可以用于客户端的双向身份验证。 | string | null | medium | per-broker | |||
ssl.keystore.password | 密钥存储文件的存储密码。这对于客户端是可选的,只有在配置ssl.keystore.location时才需要。 | password | null | medium | per-broker | |||
ssl.keystore.type | 密钥存储文件的文件格式。这对于客户是可选的。 | string | JKS | medium | per-broker | |||
ssl.protocol | 用于生成SSLContext的SSL协议。默认设置是TLS,这在大多数情况下是可以的。最近的JVMs允许的值是TLS、TLSv1.1和TLSv1.2。在旧的JVMs中可能支持SSL、SSLv2和SSLv3,但是由于已知的安全漏洞,不鼓励使用它们。 | string | TLS | medium | per-broker | |||
ssl.provider | 用于SSL连接的安全提供程序的名称。默认值是此JVM的默认安全提供程序。 | string | null | medium | per-broker | |||
ssl.trustmanager.algorithm | 信任管理器工厂用于SSL连接的算法。默认值是为此Java虚拟机配置的信任管理器工厂算法。 | string | PKIX | medium | per-broker | |||
ssl.truststore.location | 信任存储文件的位置。 | string | null | medium | per-broker | |||
ssl.truststore.password | 信任存储文件的密码。如果未设置密码,则对信任库的访问仍然可用,但已禁用完整性检查。 | password | null | medium | per-broker | |||
| 信任存储文件的文件格式。 | string | JKS | medium | per-broker | |||
alter.config.policy.class.name | 用于验证的alter configs策略类。此类应该实现 org.apache.kafka.server.policy.AlterConfigPolicy 接口。 | class | null | low | read-only | |||
alter.log.dirs.replication.quota.window.num | 为更改日志目录复制配额而保留在内存中的示例数 | int | 11 | [1,...] | low | read-only | ||
alter.log.dirs.replication.quota.window.size.seconds | 为更改日志目录复制配额的每个示例的时间跨度 | int | 1 | [1,...] | low | read-only | ||
authorizer.class.name | 应用于授权的authorizer(授权)类 | string | "" | low | read-only | |||
client.quota.callback.class | 实现ClientQuotaCallback接口的类的完全限定名,该接口用于确定应用于客户机请求的配额限制。默认情况下,或应用ZooKeeper中存储的配额。对于任何给定的请求,应用与会话的用户主体和请求的客户机id匹配的最特定配额。 | class | null | low | read-ony | |||
connection.failed.authentication.delay.ms | 失败身份验证时的连接关闭延迟:这是身份验证失败时连接关闭延迟的时间(毫秒)。必须将其配置为小于connections.max.idle.ms以防止连接超时。 | int | 100 | [0,...] | low | read-only | ||
create.topic.policy.class.name | 应用于验证的创建主题策略类。类应该实现 org.apache.kafka.server.policy.CreateTopicPolicy 接口。 | class | null | low | read-only | |||
delegation.token.expiry.check.interval.ms | 移除过期委派指令的扫描间隔 | long | 3600000 | [1,...] | low | read-only | ||
kafka.metrics.polling.interval.secs | 可在kafka.metrics.reporters实现中使用的度量轮询间隔(秒)。 | int | 10 | [1,...] | low | read-only | ||
kafka.metrics.reporters | 用作Yammer度量自定义报告程序的类列表。报告器应该实施kafka.metrics.KafkaMetricsReporter 。如果客户机希望公开自定义报告器上的JMX操作,则自定义报告器需要另外实现一个MBean特性,该特性扩展kafka.metrics.KafkaMetricsReporterMBean 特性,以便注册的MBean符合标准MBean约定。 | list | "" | low | read-only | |||
listener.security.protocol.map | 监听器名称和安全协议之间的映射。必须对相同的安全协议进行定义,才能在多个端口或IP中使用。例如,内部和外部通信流可以分离,即使两者都需要SSL。具体地说,用户可以使用内部和外部名称定义监听器,这个属性为:`INTERNAL:SSL,EXTERNAL:SSL`。如图所示,键和值由冒号分隔,映射条目由逗号分隔。每个侦听器名称只应在映射中出现一次。可以为每个侦听器配置不同的安全性(SSL和SASL)设置,方法是在配置名称中添加一个规范化前缀(侦听器名称小写)。例如,要为内部侦听器设置不同的密钥库,将设置名为listener.name.internal.ssl.keystore.location 的配置。如果未设置侦听器名称的配置,则配置将回退到通用配置(即 ssl.keystore.location )。 | string | PLAINTEXT:PLAINTEXT,SSL:SSL,SASL_PLAINTEXT:SASL_PLAINTEXT,SASL_SSL:SASL_SSL | low | per-broker | |||
log.message.downconversion.enable | 此配置控制是否启用消息格式的向下转换以满足使用请求。当设置为false时,代理不会为期望使用旧消息格式的消费者执行向下转换。对于来自此类旧客户端的使用请求,代理以 UNSUPPORTED_VERSION 错误响应。此配置不适用于复制到追随者可能需要的任何消息格式转换。 | boolean | true | low | cluster-wide | |||
metric.reporters | 用于作为度量报告器的类列表。实现org.apache.kafka.common.metrics.MetricsReporter接口允许插入将收到新度量创建通知的类。JmxReporter总是包含在注册JMX统计信息中 | list | "" | low | cluster-wide | |||
metrics.num.samples | 为计算度量而维护的样本数。 | int | 2 | [1,...] | low | read-only | ||
metrics.recording.level | 度量的最高记录级别。 | string | INFO | low | read-only | |||
metric.sample.window.ms | 计算度量样本的时间窗口。 | long | 30000 | [1,..] | low | read-only | ||
password.encoder.cipher.algorithm | 用于对动态配置的密码进行编码的密码算法。 | string | AES/CBC/PKCS5Padding | low | read-only | |||
password.encoder.iterations | 用于对动态配置的密码进行编码的迭代计数。 | int | 4096 | [1024,...] | low | read-only | ||
password.encoder.key.length | 用于对动态配置的密码进行编码的密钥长度。 | int | 128 | [8,...] | low | read-only | ||
password.encoder.keyfactory.algorithm | 用于编码动态配置密码的SecretKeyFactory 算法。默认值是PBKDF2WithHmacSHA512(如果可用),否则PBKDF2WithHmacSHA1。 | string | null | low | read-only | |||
quota.window.num | 为客户端配额在内存中保留的样本数。 | int | 11 | [1,...] | low
| read-only | ||
quota.window.size.seconds | 客户端配额的每个样本的时间跨度 | int | 1 | [1,...] | low | read-only | ||
replication.quota.window.num | 为复制配额保留在内存中的样本数 | int | 11 | [1,...] | low | read-only | ||
replication.quota.window.size.seconds | 复制配额的每个样本的时间跨度 | int | 1 | [1,...] | low | read-only | ||
ssl.endpoint.identification.algorithm | 使用服务器证书验证服务器主机名的端点标识算法。 | string | https | low | per-broker | |||
ssl.principal.mapping.rules | 用于从客户端证书的专有名称映射到短名称的规则列表。规则按顺序计算,第一个匹配主体名称的规则用于将其映射到短名称。列表中的任何后面的规则都将被忽略。默认情况下,X.500证书的专有名称将是主体。有关格式的更多信息,请参见安全授权和acl。注意,如果principal.builder.class配置提供了KafkaPrincipalBuilder的扩展,则忽略该配置。 | list | DEFAULT | low | read-only | |||
ssl.secure.random.implementation | 用于SSL加密操作的SecureRandom PRNG实现。 | string | null | low | per-broker | |||
transaction.abort.timed.out.transaction.cleanup.interval.ms | 回滚超时事务的时间间隔 | int | 60000 | [1,....] | low | read-only | ||
transaction.remove.expired.transaction.cleanup.interval.ms | 删除由于 | int | 3600000 | [1,...] | low | read-only | ||
zookeeper.sync.time.ms | 一个ZK follower 能落后一个 ZK leader 多远 | int | 2000 | low | read-only |
有关代理配置的更多详细信息,请参见scala类 kafka.server.KafkaConfig
。
3.1.1 Updating Broker Configs
从Kafka 1.1版开始,可以在不重新启动代理的情况下更新一些代理配置。有关每个代理配置的更新模式,请参阅代理配置中的 Dynamic Update Mode
列。
read-only
: 需要重新启动代理进行更新.per-broker
: 可以为每个代理动态更新cluster-wide
:可以作为集群范围的默认值动态更新。也可以根据每个代理的测试值进行更新
要更改代理 id 0 的当前代理配置(例如,日志清理线程数):
bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type brokers --entity-name 0 --alter --add-config log.cleaner.threads=2
要描述代理 id 0 的当前动态代理配置,请执行以下操作:
bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type brokers --entity-name 0 --describe
要删除配置覆盖并恢复到代理 id 0的静态配置或默认值(例如,日志清理线程数):
bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type brokers --entity-name 0 --alter --delete-config log.cleaner.threads
一些配置可以配置为集群范围的默认配置,以在整个集群中保持一致的值。集群中的所有代理都将处理集群默认更新。例如,要更新所有代理上的日志清理线程,请执行以下操作:
> bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type brokers --entity-default --alter --add-config log.cleaner.threads=2
要描述当前配置的动态集群范围默认配置:
> bin/kafka-configs.sh --bootstrap-server localhost:9092 --entity-type brokers --entity-default --describe
可以在集群级别配置的所有配置也可以在每个代理级别配置(例如用于测试)。如果在不同级别定义了配置值,则使用以下优先顺序:
- 存储在ZooKeeper中的每个代理的动态配置
- 存储在ZooKeeper中动态集群范围的默认配置
- server.properties中的静态代理配置
- Kafka默认值,请参见 broker configs
动态更新密码配置
动态更新的密码配置值在存储到ZooKeeper之前会被加密。必须在 server.properties
中配置 代理配置password.encoder.secret
以启用密码配置的动态更新。不同的代理可能会有不同的密码。
用于密码编码的秘密可以随着代理的滚动重新启动而旋转。静态代理配置 password.encoder.old.secret
中必须提供当前用于编码ZooKeeper中密码的旧秘密, password.encoder.secret
t中必须提供新秘密。
在kafka 1.1.x中,在使用kafka-configs.sh更新配置时,即使没有更改密码配置,也必须在每个alter请求中提供所有动态更新的密码配置。此约束将在将来的版本中删除。
在启动代理之前更新ZooKeeper中的密码配置
从kafka 2.0.0开始,kafka-configs.sh允许在启动代理进行引导之前使用ZooKeeper更新动态代理配置。这样可以将所有密码配置以加密形式存储,从而避免在server.properties中清除密码。如果alter命令中包含任何密码配置,还必须指定broker 配置password.encoder.secret。还可以指定其他加密参数。密码编码器配置不会保留在ZooKeeper中。例如,要在代理0上存储侦听器内部的SSL密钥密码,请执行以下操作:
> bin/kafka-configs.sh --zookeeper localhost:2181 --entity-type brokers --entity-name 0 --alter --add-config
'listener.name.internal.ssl.key.password=key-password,password.encoder.secret=secret,password.encoder.iterations=8192'
配置 listener.name.internal.ssl.key.password
将使用提供的编码器配置以加密形式保存在ZooKeeper中。编码器秘密和迭代不会持久存在于ZooKeeper中。
更新现有侦听器的SSL密钥库
代理可以配置短有效期的SSL密钥库,以降低受损证书的风险。可以在不重新启动代理的情况下动态更新密钥存储库。配置名必须以监听器前缀listener.name.{listenerName}作为前缀。因此,只更新特定侦听器的密钥库配置。以下配置可以在每个代理级别的单个alter请求中更新:
ssl.keystore.type
ssl.keystore.location
ssl.keystore.password
ssl.key.password
如果侦听器是代理间侦听器,则仅当为该侦听器配置的信任库信任新的密钥库时,才允许进行更新。对于其他侦听器,代理不会在密钥存储库上执行信任验证。证书必须由签署旧证书的同一证书颁发机构签署,以避免任何客户机身份验证失败。
更新现有侦听器的SSL信任存储
可以动态更新代理信任存储库,而无需重新启动代理来添加或删除证书。更新的信任存储库将用于对新客户机连接进行身份验证。配置名必须以监听器前缀listener.name.{listenerName}作为前缀。因此,只更新特定侦听器的信任库配置。以下配置可以在每个代理级别的单个alter请求中更新:
ssl.truststore.type
ssl.truststore.location
ssl.truststore.password
如果侦听器是代理间侦听器,则只有在新信任库信任该侦听器的现有密钥库时,才允许更新。对于其他侦听器,代理在更新之前不执行信任验证。从新的信任存储库中删除用于签署客户端证书的CA证书可能导致客户端身份验证失败。
更新默认主题配置
代理使用的默认主题配置选项可以在不重启代理的情况下更新。配置应用于没有主题配置覆盖的主题,而每个主题配置对应一个主题。这些配置中的一个或多个可以在所有代理都使用的集群默认级别上重写。
log.segment.bytes
log.roll.ms
log.roll.hours
log.roll.jitter.ms
log.roll.jitter.hours
log.index.size.max.bytes
log.flush.interval.messages
log.flush.interval.ms
log.retention.bytes
log.retention.ms
log.retention.minutes
log.retention.hours
log.index.interval.bytes
log.cleaner.delete.retention.ms
log.cleaner.min.compaction.lag.ms
log.cleaner.min.cleanable.ratio
log.cleanup.policy
log.segment.delete.delay.ms
unclean.leader.election.enable
min.insync.replicas
max.message.bytes
compression.type
log.preallocate
log.message.timestamp.type
log.message.timestamp.difference.max.ms
从Kafka 2.0.0版开始,当动态更新配置 unclean.leader.election.enable
时,控制器会自动启用未清除的领导者选择。在Kafka 1.1.x版中,更改为 unclean.leader.election.enable
仅在选择新控制器时生效。可通过运行以下命令强制控制器重新选择:
> bin/zookeeper-shell.sh localhost
rmr /controller
更新日志清洗器配置
日志清理器配置可以在所有代理使用的集群默认级别上动态更新。更改将在下次日志清理迭代时生效。可以更新其中一个或多个配置:
log.cleaner.threads
log.cleaner.io.max.bytes.per.second
log.cleaner.dedupe.buffer.size
log.cleaner.io.buffer.size
log.cleaner.io.buffer.load.factor
log.cleaner.backoff.ms
更新线程配置
代理使用的各种线程池的大小可以在所有代理使用的集群默认级别上动态更新。更新被限制在 currentSize / 2
到 currentSize * 2
的范围内,以确保正确处理配置更新。
num.network.threads
num.io.threads
num.replica.fetchers
num.recovery.threads.per.data.dir
log.cleaner.threads
background.threads
更新ConnectionQuota(连接配额)配置
代理允许的给定IP/主机的最大连接数可以在所有代理使用的集群默认级别上动态更新。这些更改将应用于新的连接创建,并且新限制将考虑现有连接计数。
max.connections.per.ip
max.connections.per.ip.overrides
添加和删除侦听器
可以动态添加或删除侦听器。添加新的侦听器时,必须以侦听器前缀 listener.name.{listenerName}
的侦听器配置形式提供侦听器的安全配置。如果新的侦听器使用SASL,则必须使用带有侦听器和机制前缀的JAAS配置属性 sasl.jaas.config
提供侦听器的JAAS配置。有关详细信息,请参阅 JAAS configuration for Kafka brokers 。
在Kafka 1.1.x版本中,代理间侦听器使用的侦听器可能不会动态更新。要将代理间侦听器更新为新的侦听器,可以在所有代理上添加新的侦听器,而无需重新启动代理。然后需要滚动重新启动才能更新 inter.broker.listener.name
。
除了新侦听器的所有安全配置之外,还可以在每个代理级别动态更新以下配置:
listeners
advertised.listeners
listener.security.protocol.map
必须使用静态代理配置 inter.broker.listener.name
或inter.broker.security.protocol
配置代理间侦听器。
3.2 Topic-Level Configs
与主题相关的配置既有一个服务器默认值,也有一个可选的每个主题覆盖。如果没有给定每个主题的配置,则使用服务器默认值。通过提供一个或多个--config选项,可以在主题创建时设置覆盖。此示例使用自定义的最大邮件大小和刷新率创建名为my-topic的主题:
[root@bigdata-senior01 kafka_2.11-1.1.0]# bin/kafka-topics.sh --zookeeper localhost:2182 --create --topic my-topic --partitions 1 --replication-factor 1 \
> --config max.message.bytes=64000 --config flush.messages=1
稍后还可以使用alter configs命令更改或设置覆盖。这个例子更新了my-topic的最大消息大小:
[root@bigdata-senior01 kafka_2.11-1.1.0]# bin/kafka-configs.sh --zookeeper localhost:2182 --entity-type topics --entity-name my-topic \
> --alter --add-config max.message.bytes=128000
要检查主题上设置的覆盖,可以执行以下操作:
[root@bigdata-senior01 kafka_2.11-1.1.0]# bin/kafka-configs.sh --zookeeper localhost:2181 --entity-type topics --entity-name my-topic --describe
要删除覆盖,可以执行以下操作:
[root@bigdata-senior01 kafka_2.11-1.1.0]# bin/kafka-configs.sh --zookeeper localhost:2182 --entity-type topics --entity-name my-topic \
> --alter --delete-config max.message.bytes
下面是主题级配置。此属性的服务器默认配置在服务器默认属性标题下给出。给定的服务器默认配置值仅适用于没有显式主题配置覆盖的主题。
NAME | DESCRIPTION | TYPE | DEFAULT | VALID VALUES | SERVER DEFAULT PROPERTY | IMPORTANCE | ||
cleanup.policy | 一个字符串,要么是“delete”,要么是“compact”。此字符串指定要在旧日志段上使用的保留策略。当达到旧日志段的保留时间或大小限制时,默认策略(“delete”)将丢弃旧日志段。“compact”将在主题上启用日志压缩。 | list | delete | [compact, delete] | log.cleanup.policy | medium | ||
compression.type | 指定给定主题的最终压缩类型。此配置接受标准压缩编解码器(“gzip”、“snappy”、“lz4”、“zstd”)。它还接受“uncompressed”,相当于没有压缩;“producer”,意味着保留生产者设置的原始压缩编解码器。 | string | producer | [uncompressed, zstd,lz4, snappy, gzip, producer] | compression.type | medium | ||
delete.retetion.ms | 为已压缩的日志主题保留 delete tombstone标记的时间量。这个设置还提供了一个时间界限,如果消费者从偏移量0开始,那么他们必须完成读取,以确保他们获得最后阶段的有效快照(否则可能在完成扫描之前收集delete tombstone)。 | long | 86400000 | [0,...] | log.cleaner.delete.retention.ms | medium | ||
file.delete.delay.ms | 从文件系统中删除文件之前等待的时间 | long | 60000 | [0,...] | log.segment.delete.delay.ms | medium | ||
flus.messages | 此设置允许指定一个间隔,在此间隔上,我们将强制将写入日志的数据进行fsync。例如,如果这个值设置为1,我们会在每条消息之后进行fsync;如果是5,我们会在每5条消息之后同步一次。一般情况下,我们建议您不要设置此选项,而是使用复制来提高持久性,并允许操作系统的后台刷新功能,因为这样更有效。可以基于每个主题重写此设置(请参阅 the per-topic configuration section)。 | long | 9223372036854775807 | [0,...] | log.flus.inerva.messages | medium | ||
flush.ms | 此设置允许指定一个时间间隔,在此时间间隔内,我们将强制对写入日志的数据进行fsync。例如,如果将其设置为1000,我们将在经过1000毫秒后进行fsync。一般来说,我们建议您不要设置此项并使用复制以提高耐久性,并且允许操作系统的后台刷新功能,因为这样更有效。 | long |
| [0,...] | log.flush.interval.ms | medium | ||
follower.replication.throttled.replicas | 日志复制应在follower端节流的副本列表。列表应该以[PartitionId]:[BrokerId]、[PartitionId]:[BrokerId]:…或者通配符“*”可用于节流此主题的所有副本。 | list | "" | [partitionId],[brokerId]:[partitionId],[brokerId]:... | follower.replication.throttled.replica | medium | ||
index.interval.bytes | 此设置控制Kafka向其偏移索引添加索引项的频率。默认设置确保我们大约每隔4096字节索引一条消息。更多的索引允许读取更接近日志中的确切位置,但会使索引更大。你可能不需要改变这个。 | int | 4096 | [0,...] | log.index.interva.bytesl | medium | ||
leader.replicatio.throttle.replicas | 应在leader端对日志复制进行节流的副本列表。列表应该以[PartitionId]:[BrokerId]、[PartitionId]:[BrokerId]:…或者通配符“*”可用于节流此主题的所有副本。 | list | "" | [partitionId],[brokerId]:[partitionId],[brokerId]:... | leader.replication.throttled.replicas | medium | ||
max.message.bytes | Kafka允许的最大记录批大小。如果此值增加,并且存在大于0.10.2的消费者,则还必须增加消费者的获取大小,以便他们能够获取如此大的记录批。 在最新的消息格式版本中,为了提高效率,记录总是分组成批。在以前的消息格式版本中,未压缩的记录不分组为批,在这种情况下,此限制仅适用于单个记录。 | int | 1000012 | [0,...] | message.max.bytes | medium | ||
message.format.version | 指定代理将用于向日志追加消息的消息格式版本。该值应该是一个有效的ApiVersion。一些示例是:0.8.2、0.9.0.0、0.10.0,请检查ApiVersion以获得更多详细信息。通过设置特定的消息格式版本,用户可以验证磁盘上所有现有的消息都小于或等于指定的版本。不正确地设置此值将导致使用旧版本的用户中断,因为他们将接收到格式不理解的消息。 | string | 2.1-IV2 | kafka.api.ApiVersionValidator$@56aac163 | log.message.format.version | medium | ||
message.timestamp.difference.max.ms | 代理程序接收消息时的时间戳与消息中指定的时间戳之间允许的最大差异。如果message.timestamp.type=CreateTime,则如果时间戳的差异超过此阈值,则消息将被拒绝。如果message.timestamp.type=LogAppendTime,则忽略此配置。 | long |
| [0,...] | log.message.timestamp.difference.max.ms | medium | ||
message.timestamp.type | 定义消息中的时间戳是消息创建时间还是日追加时间。值应为“CreateTme”或“LogAppendTime”` | string | CreateTime | [CreateTime, LogAppendTime] | log.message.timestamp.type | medium | ||
min.cleanable.dirty.ratio | 此配置控制日志压缩器尝试清理日志的频率(假设启用了日志压缩)。默认情况下,我们将避免清理已经压缩了50%以上的日志。这个比率限定了重复操作在日志中浪费的最大空间(50%时,最多50%的日志可以是重复操作)。更高的比率将意味着更少、更有效的清理,但将意味着日志中更多的浪费空间。 | double | 0.5 | [0,...,1] | log.cleaner.min.cleanable.ratio | medium | ||
min.compaction.lag.ms | 消息在日志中保持未压缩的最小时间。仅适用于正在压缩的日志。 | long | 0 | [0,...] | log.cleaner.min.compaction.lag.ms | medium | ||
min.insync.replicas | 当生产者将acks设置为“all”(或“-1”)时,此配置指定必须确认写入才能认为成功的最小副本数。如果不能满足此最小值,则生产者将引发异常(NotEnoughReplicas 或NotEnoughReplicasAfterAppend)。在一起使用时min.insync.replicas 和 acks 允许您强制执行更高的持久性保证。典型的场景是创建一个复制因子为3的主题,将min.insync.replicas 设置为2,并使用 acks “all”生成。这将确保生产者在大多数副本没有收到写操作时引发异常。 | int | 1 | [1,...] | min.insync.replicas | medium | ||
preallocate | 如果我们在创建新的日志段时在磁盘上预先分配文件,则为True。 | boolean | false | log.preallocate | medium | |||
retention.bytes | 如果使用“delete”保留策略,此配置控制分区(由日志段组成)可以增长到的最大大小,然后我们将丢弃旧日志段以释放空间。默认情况下,没有大小限制,只有时间限制。因为这个限制是在分区级别强制执行的,所以将它乘以分区数,以字节为单位计算主题保留。 | long | -1 | log.retention.bytes | medium | |||
retention.ms | 如果使用“delete”保留策略,此配置将控制在丢弃旧日志段以释放空间之前保留日志的最长时间。这表示有关消费者必须多久读取数据的SLA。如果设置为-1,则不应用时间限制。 | long |
| log.retention.ms | medium | |||
segment.bytes | 此配置控制日志的段文件大小。保留和清理总是一次完成一个文件,因此较大的段大小意味着更少的文件,但对保留的控制就更少了。 | int | 1073741824 | [14,...] | log.segment.bytes | medium | ||
segment.index.bytes | 此配置控制将偏移映射到文件位置的索引的大小。我们预先分配这个索引文件,只有在日志滚动之后才收缩它。通常不需要更改此设置。 | int | 10485760 | [0,...] | log.index.size.max.bytes | medium | ||
segment.jitter.ms | 为了以避免雷鸣般的区段滚动而从预定段滚动时间中减去的最大随机抖动 | long | 0 | [0,...] | log.roll.jitter.ms | medium | ||
segment.ms | 此配置控制一段时间,在此之后,即使段文件未满,Kafka也会强制滚动日志,以确保保留可以删除或压缩旧数据。 | long | 604800000 | [1,...] | log.roll.ms | medium | ||
unclean.leader.election.enable | 指示是否允许不在ISR集中的副本被选为最终的领导者,即使这样做可能会导致数据丢失。 | boolean | false | unclean.leader.election.enable | medium | |||
message.downconversion.enable | 此配置控制是否启用消息格式的下转换以满足消费请求。当设置为false时,broker将不会为期望较旧消息格式的消费者执行下转换。对于来自此类老客户端的消费请求,代理将使用UNSUPPORTED_VERSION 错误进行响应。此配置不适用于复制到追随者可能需要的任何消息格式转换。 | boolean | true | log.message.downconversion.enable | low |
3.3 Producer Configs
以下是生产者的配置:
NAME | DESCRIPTION | TYPE | DEFAULT | VALID VALUES | IMPORTANCE |
key.serializer | 实现org.apache.kafka.common.serialization.Serializer 接口的键的序列化程序类。 | class | high | ||
value.serializer | 实现org.apache.kafka.common.serialization.Serializer 接口的值的序列化程序类。 | class | high | ||
acks | 生产者在考虑完成请求之前要求领导者收到的确认数。这将控制发送的记录的持久性。允许以下设置:
| string | 1 | [all,-1,0,1] | high |
bootstrap.servers | 用于建立与Kafka群集的初始连接的主机/端口对列表。客户机将使用所有服务器,而不管在此处指定用于引导的服务器是什么,此列表只影响用于发现完整服务器集的初始主机。此列表的格式应为host1:port1,host2:port2,...。 由于这些服务器只是用于初始连接以发现完整的群集成员身份(可能会动态更改),因此此列表不需要包含完整的服务器集(不过,在服务器关闭时,您可能需要多个服务器)。 | list | "" | non-null string | high |
buffer.memory | 生产者可用于缓冲等待发送到服务器的记录的内存总字节数。如果记录发送的速度比发送到服务器的速度快,那么生产者将阻塞
| long | 33554432 | [0,...] | high |
compression.type | 生产者生成的所有数据的压缩类型。默认值为none(即无压缩)。有效值为 none , gzip , snappy , lz4 , or zstd . 压缩是整批数据,因此分批的效果也会影响压缩比(越多分批意味着更好的压缩)。 | string | none | high | |
retries | 设置一个大于零的值将导致客户端重新发送任何发送失败的记录,并可能出现暂时错误。请注意,此重试与客户机在收到错误后重新发送记录没有什么不同。如果不将max.in.flight.requests.per.connection 设置为1,则允许重试可能会更改记录的顺序,因为如果将两个批发送到单个分区,而第一个批失败并重试,但第二个批成功,则第二批中的记录可能会首先出现。注意:另外,如果delivery.timeout.ms 配置的超时在成功确认之前先过期,则在重试次数用完之前,生成请求将失败。 | int | 2147483647 | [0,...,2147483647] | high |
ssl.key.password | 密钥存储文件中私钥的密码。这对于客户是可选的。 | password | null | high | |
ssl.keystore.location | 密钥存储文件的位置。这对于客户机是可选的,可以用于客户机的双向身份验证。 | string | null | high | |
ssl.keystore.password | 密钥存储文件的存储密码。这对于客户端是可选的,只有在配置ssl.keystore.location时才需要。 | password | null | high | |
ssl.truststore.location | 信任存储文件的位置。 | string | null | high | |
ssl.truststore.password | 信任存储文件的密码。如果没有设置密码,对信任库的访问仍然可用,但已禁用完整性检查。 | password | null | high | |
batch.size | 每当将多个记录发送到同一分区时,生产者将尝试将记录一起批处理成更少的请求。这有助于客户机和服务器上的性能。此配置以字节为单位控制默认批处理大小。
不会尝试批处理大于此大小的记录。
发送给代理的请求将包含多个批,每个分区对应一个批,其中包含要发送的可用数据。
小批量将使批处理不太常见,并可能降低吞吐量(批量大小为零将完全禁用批处理)。一个非常大的批处理大小可能会更加浪费内存,因为我们总是在预期会有额外的记录时分配指定批处理大小的缓冲区。 | int | 16384 | [0,...] | medium |
client.dns.lookup | 控制客户端如何使用DNS查找。
如果将其设置为
如果值为 | string | default | [default, use_all_dns_ips, resolve_canonical_bootstrap_servers_only] | medium |
client.id | 发出请求时传递给服务器的ID字符串。这样做的目的是,通过允许在服务器端请求日志记录中包含逻辑应用程序名,可以跟踪不仅仅是 ip/port 的请求源。 | string | "" | medium | |
connections.max.idle.ms | 在此配置指定的毫秒数之后关闭空闲连接。 | long | 540000 | medium | |
delivery.timeout.ms | 在send() 调用返回后,报告成功或失败时间的上限。这限制了发送前记录将被延迟的总时间、等待代理确认的时间(如果预期的话)以及允许可重试发送失败的时间。如果遇到不可恢复的错误、重试已用尽,或者记录被添加到到达较早交付截止日期的批处理中,那么生产者可能会报告未能在此配置之前发送记录。此配置的值应大于或等于 request.timeout.ms 和 linger.ms 的 和。 | int | 120000 | [0,...] | medium |
linger.ms | 生产者将在请求传输之间到达的所有记录分组为单个批处理请求。通常,只有当记录到达的速度快于发送的速度时,才会在负载下发生这种情况。然而,在某些情况下,即使在中等负载下,客户机也可能希望减少请求的数量。这个设置通过添加少量的人为延迟来实现这一点,也就是说,与立即发送一条记录相比,生产者将等待最多给定的延迟来允许发送其他记录,以便将发送组合在一起。这可以看作类似于TCP中的Nagle算法。这个设置给出了批处理延迟的上限:此设置默认为0(即无延迟)。例如,将linger.ms=5设置为可以减少发送的请求数,但对于在没有加载的情况下发送的记录,这会增加5毫秒的延迟。
| int | 0 | [0,...] | medium |
max.block.ms | 配置控制
| long | 60000 | [0,...] | medium |
max.request.size | 请求的最大大小(以字节为单位)。此设置将限制生产者在单个请求中发送的记录批次的数量,以避免发送巨大的请求。这也有效地限制了最大记录批大小。注意,服务器对记录批大小有自己的上限,这可能与此不同。 | int | 1048576 | [0,..] | medium |
partitioner.class | 实现org.apache.kafka.clients.producer.Partitioner 接口的分区器类 | class | org.appache.clients.producer.internals.DefaultPartitioner | medium | |
receive.buffer.bytes | 读取数据时使用的TCP接收缓冲区(SO_RCVBUF)的大小。如果值为-1,则使用OS默认值。 | int | 32768 | [-1,...] | medium |
request.timeout.ms | 此配置控制客户机等待请求响应的最大时间量。如果超时时间结束之前没有收到响应,客户端将在必要时重新发送请求,或者在重试耗尽时请求失败。这个应该大于replica.lag.time.max.ms (代理配置)以减少由于不必要的生成者重试而导致消息重复的可能性。 | int | 300000 | [0,...] | medium |
sasl.client.callback.handler.class | 实现AuthenticateCallbackHandler接口的SASL客户端回调处理程序类的完全限定名。 | class | null | medium | |
sasl.jaas.config | 用于SASL连接的JAAS登录上下文参数,格式为JAAS配置文件使用的格式。 here描述了JAAS配置文件格式。值的格式为:'loginModuleClass controlFlag (optionName=optionValue)*;' 。 对于代理,配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如:istener.name.sasl_ssl.scram-sha-256.sasl.jaas.config=com.example.ScramLoginModule是必须的 | password | null | medium | |
sasl.kerberos.service.name | 运行Kafka的Kerberos主体名称。这可以在Kafka的JAAS配置或Kafka的配置中定义。 | string | null | medium | |
sasl.login.callback.handler.class | 实现AuthenticateCallbackHandler接口的SASL登录回调处理程序类的完全限定名。对于代理,登录回调处理程序配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.login.callback.handler.class=com.example.customscramlogincallbackhandler | class | null | medium | |
sasl.login.class | 实现Login接口的类的完全限定名。对于代理,登录配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.login.class=com.example.customscramlogin | class | null | medium | |
sasl.mechanism | 用于客户端连接的SASL机制。这可能是安全提供程序可用的任何机制。GSSAPI是默认机制。 | string | GSSAPI | medium | |
security.protocol | 用于与代理通信的协议。有效值为:PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. | string | PLAINTEXT | medium | |
send.buffer.bytes | 发送数据时使用的TCP发送缓冲区(SO_SNDBUF)的大小。如果值为-1,则使用OS默认值。 | int | 131072 | [-1,..] | medium |
ssl.enabled.protocols | 为SSL连接启用的协议列表。 | list | TLSv1.2,TLSv1.1,TLSv1 | medium | |
ssl.keystore.type | 密钥存储文件的文件格式。这对于客户是可选的。 | string | JKS | medium | |
ssl.protocol | 用于生成SSLContext的SSL协议。默认设置是TLS,这在大多数情况下是可以的。最近的JVMs允许的值是TLS、TLSv1.1和TLSv1.2。在旧的JVMs中可能支持SSL、SSLv2和SSLv3,但是由于已知的安全漏洞,不鼓励使用它们。 | string | TLS | medium | |
ssl.provider | 用于SSL连接的安全提供程序的名称。默认值是JVM的默认安全提供程序。 | string | null | medium | |
ssl.truststore.type | 信任存储文件的文件格式。 | string | JKS | medium | |
enable.idempotence | 当设置为“true”时,生产者将确保在流中准确地写入每个消息的一个副本。如果“false”,由于代理失败等原因生产者重试可能会在流中写入重试消息的副本。请注意,启用等幂要求max.in.flight.requests.per.connection 小于或等于5,retries 大于0,acks 必须为“all”。如果用户没有明确设置这些值,将选择合适的值。如果设置了不兼容的值,将引发ConfigException 。 | boolean | false | low | |
interceptor.classes | 用作拦截器的类的列表。实现org.apache.kafka.clients.producer.ProducerInterceptor 接口允许您截取(并且可能改变)在发布到kafka集群之前由生产者接收的记录。默认情况下,没有拦截器。 | list | "" | non-null string | low |
max.in.flight.requests.per.connection | 客户端在阻止前在单个连接上发送的未确认请求的最大数目。注意,如果该设置被设置为大于1且发送失败,则由于重试(即如果启用了重试),会有重新排序消息的风险。 | int | 5 | [1,...] | low |
metadata.max.age.ms | 在这段时间(以毫秒为单位)之后,即使我们没有看到任何分区leadership更改以主动发现任何新代理或分区,也会强制刷新元数据。 | long | 300000 | [0,...] | low |
metric.reporters | 用作度量报告程序的类的列表。实现org.apache.kafka.common.metrics.metricsreporter接口允许插入将收到新度量创建通知的类。JmxReporter总是包含在注册JMx统计信息中。 | list | "" | non-nul string | low |
...... | ...... | ...... | ...... | ...... | ...... |
3.4 Consumer Configs
以下是消费者的配置:
NAME | DESCRIPTION | TYPE | DEFAULT | VALID VALUES | IMPORTANCE |
key.deserializer | 实现org.apache.kafka.common.serialization.Deserializer 接口的键的反序列化程序类。 | class | high | ||
value.deserializer | 实现org.apache.kafka.common.serialization.Deserializer 接口的值的反序列化程序类。 | class | high | ||
bootstrap.servers | 用于建立与Kafka群集的初始连接的主机/端口对列表。客户机将使用所有服务器,而不管在此处指定用于引导的服务器是什么,此列表只影响用于发现完整服务器集的初始主机。此列表的格式应为host1:port1,host2:port2,... .。由于这些服务器只是用于初始连接以发现完整的群集成员身份(可能会动态更改),因此此列表不需要包含完整的服务器集(但是,如果服务器关闭,您可能需要多个服务器)。 | list | "" | non-null string | high |
fetch.min.bytes | 服务器应该为获取请求返回的最小数据量。如果没有足够的数据可用,则请求将等待大量数据累积后才响应请求。默认设置为1个字节意味着一旦有一个字节的数据可用,或者fetch请求超时等待数据到达,就会立即响应fetch请求。将此值设置为大于1将导致服务器等待更大数量的数据累积,这可以稍微提高服务器吞吐量,但代价是增加一些延迟。 | int | 1 | [0,...] | high |
group.id | 标识此消费者所属的消费者组的唯一字符串。如果消费者通过使用subscribe(topic)来使用组管理功能 或 使用基于kafka的偏移管理策略,则需要此属性。 | string | "" | high | |
heartbeat.interval.ms | 使用Kafka的组管理工具时,消费者协调器预期的心跳间隔时间。心跳用于确保消费者的会话保持活动状态,并在新消费者加入或离开该组时促进再平衡。该值必须设置为session.timeout.ms 以下,但通常应设置不高于该值的1/3。它可以调整甚至更低,以控制正常再平衡的预期时间。 | int | 3000 | high | |
max.partition.fetch.bytes | 服务器将返回的每个分区的最大数据量。消费者批量提取记录。如果fetch的第一个非空分区中的第一个记录批大于这个限制,那么仍然会返回该批,以确保使用者能够取得进展。代理接受的最大记录批处理大小是通过message.max.bytes (broker config) 或 max.message.bytes (topic config)定义的。有关限制使用者请求大小的信息,请参阅fetch.max.bytes。 | int | 1048576 | [0,...] | high |
session.timeout.ms | 使用Kafka的组管理工具时用于检测消费者故障的超时。消费者会定期向经纪人发送心跳,以表明自己的活跃程度。如果在此会话超时过期之前代理没有接收到心跳,则代理将从组中删除该消费者并启动重新平衡。请注意,该值必须在代理配置中由group.min.session.timeout.ms 和 group.max.session.timeout.ms .配置的允许范围内。 | int | 10000 | high | |
ssl.key.password | 密钥存储文件中私钥的密码。这对于客户是可选的。 | password | null | high | |
ssl.keystore.location | 密钥存储文件的位置。这对于客户端是可选的,可以用于客户端的双向身份验证。 | string | null | high | |
ssl.keystore.password | 密钥存储文件的存储密码。这对于客户端是可选的,只有在配置ssl.keystore.location时才需要。 | password | null | high | |
ssl.truststore.location | 信任存储文件的位置。 | string | null | high | |
ssl.truststore.password | 信任存储文件的密码。如果未设置密码,则对信任库的访问仍然可用,但已禁用完整性检查。 | password | null | high | |
auto.offset.reset | 当Kafka中没有初始偏移量,或者当前偏移量在服务器上不存在时(例如,因为数据已被删除),该怎么办?
| string | lastest | [latest,earliest,none] | medium |
client.dns.lookup | 控制客户端如何使用DNS查找。
如果将其设置为
如果值为 | string | default | [default, use_all_dns_ips, resolve_canonical_bootstrap_servers_only] | medium |
connections.max.idle.ms | 在此配置指定的毫秒数之后关闭空闲连接。 | long | 5400000 | medium | |
default.api.timeout.ms | 为可能阻塞的消费者API指定超时(以毫秒为单位)。此配置用于不显式接受timeout 参数的所有消费者操作的默认超时。 | int | 60000 | [0,...] | medium |
enable.auto.commit | 如果为真,消费者的偏移量将在后台定期提交。 | boolean | true | medium | |
exclude.internal.topics | 来自内部主题(如偏移)的记录是否应向消费者公开。如果设置为 true ,从内部主题接收记录的唯一方法就是订阅它。 | boolean | true | medium | |
fetch.max.bytes | 服务器应为获取请求返回的最大数据量。记录由消费者分批提取,如果提取的第一个非空分区中的第一个记录批大于此值,则仍将返回该记录批,以确保消费者能够取得进展。因此,这不是绝对最大值。代理接受的最大记录批处理大小是通过message.max.bytes (broker config) 或 max.message.bytes (topic config).定义的。请注意,消费者并行执行多个取操作。 | int | 52428800 | [0,...] | medium |
isolation.level | 控制如何读取事务性写入的消息。如果设置为
消息将始终按偏移顺序返回。消息总是按偏移量顺序返回。因此,在
此外,在 | string | read_uncommitted | [read_committed, read_uncommitted] | medium |
max.poll.interval.ms | 使用消费者组管理时,poll()调用之间的最大延迟。这就为消费者在获取更多记录之前空闲的时间设置了上限。如果在此超时过期之前未调用poll(),则认为消费者失败,组将重新平衡,以便将分区重新分配给另一个成员。 | int | 300000 | [1,....] | medium |
max.poll.records | 在对poll()的单个调用中返回的最大记录数。 | int | 500 | [1,...] | medium |
partition.assignment.strategy | 使用组管理时,客户端将用于在消费者实例之间分配分区所有权的分区分配策略的类名。 | list | class org.apache.kafka.clients.consumer.RangeAssignor | non-nul string | medium |
receive.buffer.bytes | 读取数据时要使用的TCP接收缓冲区(SO_RCVBU)的大小。如果值为-1,将使用操作系统默认值。 | int | 65536 | [-1,...] | medium |
request.timeout.ms | 此配置控制客户端等待请求响应的最长时间。如果在超时时间结束之前没有收到响应,则客户端将在必要时重新发送请求,或者在重试次数用完时使请求失败。 | int | 3000 | [0,...] | medium |
sasl.client.callback.handler.class | 实现AuthenticateCallbackHandler接口的SASL客户端回调处理程序类的完全限定名。 | class | null | medium | |
sasl.jaas.config | 用于SASL连接的JAAS登录上下文参数,格式为JAAS配置文件使用的格式。 here描述了JAAS配置文件格式。值的格式为:'loginModuleClass controlFlag (optionName=optionValue)*; ' 。对于代理,配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.jaas.config=com.example.ScramLoginModule是必需的; | password | null | medium | |
sasl.kerberos.service.name | 运行Kafka的Kerberos主体名称。这可以在Kafka的JAAS配置或Kafka的配置中定义。 | string | null | medium | |
sasl.login.callback.handler.class | 实现AuthenticateCallbackHandler接口的SASL登录回调处理程序类的完全限定名。对于代理程序,登录回调处理程序配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.login.callback.handler.class=com.example.CustomScramLoginCallbackHandler | class | null | medium | |
sasl.login.class | 实现登录接口的类的完全限定名。对于代理,登录配置必须以侦听器前缀和SASL机制名称(小写)作为前缀。例如,listener.name.sasl_ssl.scram-sha-256.sasl.login.class=com.example.CustomScramLogin | class | null | medium | |
sasl.mechanism | 用于客户端连接的SASL机制。这可能是安全提供程序可用的任何机制。GSSAPI是默认机制。 | string | GSSAPI | medium | |
security.protocol | 用于与代理通信的协议。有效值为:PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL. | string | PLAINTEXT | medium | |
send.buffer.bytes | 发送数据时要使用的TCP发送缓冲区(SO_SNDBUF)的大小。如果值为-1,将使用操作系统默认值。 | int | 131072 | [-1,...] | medium |
ssl.enabled.protocols | 为SSL连接启用的协议列表。 | list | TLSv1.2,TLSv1.1,TLSv1 | medium | |
ssl.keystore.type | 密钥存储文件的文件格式。这对于客户是可选的 | string | JKS | medium | |
ssl.protocol | 用于生成SSLContext的SSL协议。默认设置为TLS,对于大多数情况都可以。最近的JVMs中允许的值是TLS, TLSv1.1 和 TLSv1.2. SSL, SSLv2 and SSLv3 。在旧的JVMs中可能支持SSL、SSLV2和SSLV3,但由于已知的安全漏洞,不鼓励使用它们。 | string | TLS | medium | |
ssl.provider | 用于SSL连接的安全提供程序的名称。默认值是JVM的默认安全提供程序。 | string | null | medium | |
ssl.truststore.type | 信任存储文件的文件格式。 | string | JKS | medium | |
...... | ...... | ...... | ...... | ...... | ...... |
4. DESIGN
4.1 Motivation(动机)
我们设计的Kafka能够作为一个统一的平台来处理大型公司可能拥有的所有实时数据馈送。要做到这一点,我们必须考虑一组相当广泛的用例。
它必须具有高吞吐量才能支持大容量事件流,如实时日志聚合。
它需要优雅地处理大型数据积压,以便能够支持从离线系统定期加载数据。
这也意味着系统将不得不处理低延迟交付来处理更传统的消息传递用例。
我们希望支持这些提要的分区、分布式、实时处理,以创建新的派生提要。这激发了我们的分区和消费者模型。
最后,在流被送入其他数据系统进行服务的情况下,我们知道系统必须能够在机器出现故障时保证容错性。
支持这些使用使我们得到了一个具有许多独特元素的设计,比传统的消息传递系统更类似于数据库日志。我们将在下面的部分中概述设计的一些元素。
4.2 Persistence
Don't fear the filesystem!
Kafka严重依赖文件系统来存储和缓存消息。人们普遍认为“磁盘速度慢”,这使得人们怀疑持久结构能否提供具有竞争力的性能。事实上,磁盘的速度比人们预期的要慢得多,速度也比人们预期的快得多,这取决于它们是如何使用的;而一个适当设计的磁盘结构通常可以和网络一样快。
关于磁盘性能的关键事实是,在过去十年中,硬盘驱动器的吞吐量一直在偏离磁盘查找的延迟。因此,在具有6个7200rpm SATA RAID-5阵列的JBOD配置上,线性写操作的性能约为600MB/秒,而随机写操作的性能仅为100k/秒——相差超过6000X。这些线性读和写是所有使用模式中最可预测的,操作系统对它们进行了大量优化。现代操作系统提供了预读和后写技术,这些技术可以以大的块倍数预取数据,并将较小的逻辑写分组为大的物理写。关于这个问题的进一步讨论可以在这篇ACM队列文章中找到;实际上,他们发现顺序磁盘访问在某些情况下比随机内存访问更快!
为了弥补这种性能差异,现代操作系统越来越积极地使用主内存进行磁盘缓存。现代操作系统会很高兴地将所有空闲内存转移到磁盘缓存中,而在回收内存时,性能损失很小。所有的磁盘读写都将经过这个统一的缓存。如果不使用直接I/O,这个特性是无法轻易关闭的,因此,即使一个进程维护了数据的进程内缓存,这个数据也可能在OS pagecache中重复,从而有效地将所有内容存储两次。
此外,我们是在JVM之上构建的,任何使用过Java内存的人都知道两件事:
1. 对象的内存开销非常高,通常会使存储的数据的大小增加一倍(或更糟)。
2. 随着堆内数据的增加,Java垃圾收集变得越来越复杂和缓慢。
由于这些因素,使用文件系统和依赖pagecache优于维护内存中的缓存或其他结构,我们至少通过自动访问所有可用内存使可用缓存翻倍,并且通过存储紧凑的字节结构而不是单个对象,可能再次翻倍。这样做将在32GB的机器上获得最多28-30GB的缓存,而不会造成GC损失。此外,即使重新启动服务,这个缓存也将保持温暖,而进程内缓存将需要在内存中重新构建(10GB缓存可能需要10分钟),否则它将需要从一个完全冷的缓存开始(这可能意味着糟糕的初始性能)。这也大大简化了代码,因为维护缓存和文件系统之间一致性的所有逻辑现在都在OS中,这比一次性的进程内尝试更有效、更正确。如果您的磁盘使用倾向于线性读取,那么read-ahead实际上是在每次读取磁盘时用有用的数据预先填充这个缓存。
这建议了一种非常简单的设计:与其在内存中尽可能多地维护,并在空间耗尽时惊慌地将其全部清空到文件系统中,还不如将其反转。所有数据都立即写入文件系统上的持久日志,而不必刷新到磁盘。实际上,这只意味着它被转移到内核的pagecache中。
Constant Time Suffices
消息传递系统中使用的持久数据结构通常是一个每个消费者的队列,具有相关的BTree或其他通用的随机访问数据结构,用于维护关于消息的元数据。Btrees是可用的最通用的数据结构,使其能够支持消息传递系统中的各种事务和非事务语义。不过,它们确实带来了相当高的成本:Btree操作是O(log N).通常O(log N)本质上等同于常量时间,但对于磁盘操作则不是这样。磁盘搜索的速度为10 ms a pop,每个磁盘一次只能执行一次搜索,因此并行性有限。因此,即使是少量的磁盘查找也会导致非常高的开销。由于存储系统混合了非常快的缓存操作和非常慢的物理磁盘操作,所以当数据随着固定缓存而增加时,树结构的观察性能通常是超线性的。将数据翻倍比将速度翻倍糟糕得多。
直观地说,持久性队列可以构建在简单的读取和附加到文件上,这与日志解决方案的常见情况一样。这种结构的优点是所有操作都是O(1),读操作不会阻塞写操作或相互阻塞。这具有明显的性能优势,因为性能完全与数据大小解耦 -- 一台服务器现在可以充分利用许多廉价的低转速1+TB SATA驱动器。尽管它们的寻道性能很差,但这些驱动器对于大型读写具有可接受的性能,价格为1/3,容量为3倍。
在没有任何性能损失的情况下访问几乎无限的磁盘空间意味着我们可以提供消息传递系统中通常没有的一些特性。例如,在Kafka中,我们可以将消息保留相对较长的时间(比如一周),而不是试图在消息被使用后立即删除它们。正如我们将要描述的,这为消费者带来了极大的灵活性。
4.3 Efficiency(效率)
我们在效率方面作出了重大努力。我们的一个主要用例是处理web活动数据,它的容量非常大:每个页面视图可能生成几十个写操作。此外,我们假定发布的每条消息至少有一个消费者(通常是许多消费者)阅读,因此我们努力使消费尽可能便宜。
我们还从构建和运行许多类似系统的经验中发现,效率是有效的多租户操作的关键。如果下游基础设施服务很容易因为应用程序使用量的小波动而成为瓶颈,那么这种小的更改常常会产生问题。通过非常快的速度,我们帮助确保应用程序在基础设施之前会在负载下翻过来。当试图在一个集中式集群上运行一个支持数十或数百个应用程序的集中式服务时,这一点尤其重要,因为使用模式的变化几乎每天都在发生。
我们在前一节讨论了磁盘效率。一旦消除了糟糕的磁盘访问模式,这种类型的系统效率低下的两个常见原因是:太多的小型I/O操作和过多的字节复制。
小的I/O问题发生在客户机和服务器之间以及服务器自己的持久操作中。
为了避免这种情况,我们的协议是围绕一个“消息集”抽象构建的,该抽象自然地将消息分组在一起。这允许网络请求将消息分组并分摊网络往返的开销,而不是一次发送一条消息。反过来,服务器一次性地将消息块添加到其日志中,而消费者一次获取大量的线性块。
这个简单的优化产生了数量级的加速。批处理会导致更大的网络数据包、更大的顺序磁盘操作、连续的内存块等等,所有这些都允许Kafka将突发的随机消息写入流转换为线性写入流,并将其传递给消费者。
另一个低效率是字节复制。在较低的消息速率下,这不是问题,但在负载下,影响是显著的。为了避免这种情况,我们使用了标准化的二进制消息格式,它由生产者、代理和使用者共享(因此可以在它们之间传输数据块而无需修改)。
由代理维护的消息日志本身就是一个文件目录,每个文件由一系列消息集填充,这些消息集以生产者和消费者使用的相同格式写入磁盘。维护这种通用格式可以优化最重要的操作:持久性日志块的网络传输。现代unix操作系统为将数据从pagecache传输到套接字提供了高度优化的代码路径;在Linux中,这是通过sendfile系统调用完成的。
要了解sendfile的影响,重要的是要了解将数据从文件传输到套接字的公共数据路径:
1. 操作系统将磁盘中的数据读入内核空间中的pagecache
2. 应用程序将数据从内核空间读入用户空间缓冲区
3. 应用程序将数据写回内核空间到套接字缓冲区
4. 操作系统将数据从套接字缓冲区复制到NIC缓冲区,并通过网络发送到NIC缓冲区
这显然是低效的,有四个副本和两个系统调用。通过使用sendfile,允许操作系统将数据从pagecache直接发送到网络,从而避免了这种重复复制。因此,在此优化路径中,只需要将最终副本复制到NIC缓冲区。
我们期望一个常见的用例是一个主题上的多个消费者。使用上面的零复制优化,数据被精确地复制到pagecache中一次,并在每次使用时重用,而不是存储在内存中,并在每次读取时复制到用户空间。这允许以接近网络连接极限的速度使用消息。
我们期望一个常见的用例是一个主题上的多个消费者。使用上面的零复制优化,数据被精确地复制到pagecache中一次,并在每次使用时重用,而不是存储在内存中,并在每次读取时复制到用户空间。这允许以接近网络连接极限的速度使用消息。
这种pagecache和sendfile的组合意味着,在Kafka集群上,用户主要集中在这里,无论如何,您都不会看到磁盘上的读取活动,因为它们将完全从缓存中提供数据。
End-to-end Batch Compression(端到端批压缩)
在某些情况下,瓶颈实际上不是CPU或磁盘,而是网络带宽。对于需要通过广域网在数据中心之间发送消息的数据管道来说,尤其如此。当然,用户可以一次压缩一条消息,而不需要Kafka的任何支持,但这会导致压缩率非常低,因为许多冗余是由于同一类型的消息之间的重复(例如JSON中的字段名或Web日志中的用户代理或公共字符串值)。
Kafka以高效的批处理格式支持这一点。可以将一批消息集中在一起,压缩后以这种形式发送到服务器。这批消息将以压缩形式编写,并将在日志中保持压缩状态,只由消费者解压缩。
Kafka支持GZIP、Snappy、LZ4和ZStandard压缩协议。
4.4 The Producer
Load balancing(负载平衡)
生产者 不需要任何中间路由层直接 将数据发送给 分区的领导者 的代理。为了帮助生成者完成这一任务,所有Kafka节点都可以响应关于哪些服务器是活动的以及主题分区的领导者在任何给定时间位于何处的元数据请求,从而允许生成者适当地指导其请求。
客户机控制将消息发布到哪个分区。这可以随机完成,实现一种随机负载平衡,也可以通过一些语义分区函数来完成。我们公开了用于语义分区的接口,允许用户指定分区的键,并使用这个键哈希到分区(如果需要,还可以重写分区函数)。例如,如果选择的键是用户id,那么给定用户的所有数据都将发送到同一个分区。这反过来将允许消费者对他们的消费做出本地化的假设。这种类型的分区被显式地设计为允许在消费者中进行对位置敏感的处理。
Asynchronous send(异步发送)
批处理是效率的主要驱动因素之一,为了启用批处理,Kafka生成器将尝试在内存中积累数据,并在单个请求中发送更大的批处理。可以将批处理配置为累积的消息不超过固定数量,等待的时间不超过某些固定的延迟界限(例如64k或10ms)。这允许在服务器上积累更多的字节来发送,并且很少有较大的I/O操作。这种缓冲是可配置的,并提供了一种机制来权衡少量额外的延迟以获得更好的吞吐量。
4.5 The Consumer
Kafka消费者通过向引导它想要消费的分区的代理发出“fetch”请求来工作。消费者在每次请求时在日志中指定其偏移量,并从该位置接收回一段日志。因此,消费者对这个位置有很大的控制权,如果需要,可以将其倒回去重新消费
Push vs. pull(推与拉)
我们首先考虑的问题是,消费者应该从代理中提取--pull数据,还是代理应该将数据推送--push给消费者。在这方面,Kafka采用了一种更传统的设计,大多数消息传递系统都共享这种设计,其中数据由生产者推送到代理,由消费者从代理中提取。一些以日志为中心的系统,如Scribe和Apache Flume,遵循非常不同的基于push的路径,其中数据被向下推送。两种方法都有优缺点。然而,由于代理控制数据传输的速率,基于push的系统很难处理不同的消费者。目标通常是让消费者能够以最大可能的速度消费;不幸的是,在push系统中,这意味着当消费率低于生产率时(本质上是拒绝服务攻击),消费者往往会不知所措。基于拉的系统具有更好的特性,消费者可以简单地落后于它,并在可能的时候赶上它。可以通过某种后退协议来缓解这种情况,通过这种协议,消费者可以指示它已不堪重负,但是要让传输速率充分利用(但绝不是过度利用)消费者要比看起来复杂得多。以前尝试以这种方式构建系统时,我们采用了更传统的pull模型。
基于拉的系统的另一个优点是,它可以积极地批量处理发送给消费者的数据。基于push的系统必须选择立即发送请求,或者积累更多的数据,然后稍后发送,而不知道下游消费者是否能够立即处理它。如果调优为低延迟,这将导致每次只发送一条消息,以便传输最终得到缓冲,这是浪费。基于拉的设计解决了这一问题,因为使用者总是在日志中当前位置之后(或达到某些可配置的最大大小)提取所有可用的消息。因此可以在不引入不必要延迟的情况下获得最佳批处理。
简单的基于拉的系统的不足之处在于,如果代理没有数据,那么消费者可能最终会在一个紧密的循环中轮询,从而有效地忙于等待数据的到来。为了避免这种情况,我们在pull请求中使用了一些参数,这些参数允许消费者请求阻塞在一个“长轮询”中,等待数据到达(也可以选择等待给定的字节数,以确保传输大小足够大)。
你可以想象其他可能的设计,只有拉,端到端的。生产者将在本地写入本地日志,而代理将从日志中提取数据,而消费者将从日志中提取数据。类似的“存储转发”生产者类型也经常被提出。这很有趣,但是我们觉得不太适合我们的目标用例,它有成千上万的生产者。我们在大规模运行持久数据系统的经验让我们觉得,在系统中跨许多应用程序使用数千个磁盘实际上不会使事情变得更可靠,而且操作起来将是一场噩梦。在实践中,我们发现可以在不需要生产者持久性的情况下大规模运行具有强SLAs的管道。
Consumer Position
令人惊讶的是,跟踪已消费的内容是消息传递系统的关键性能点之一。
大多数消息传递系统都保存有关代理上使用了哪些消息的元数据。也就是说,当消息发送给消费者时,代理要么立即在本地记录该事实,要么等待消费者的确认。这是一个相当直观的选择,而且对于单台机器服务器来说,还不清楚这种状态还能发展到什么地方。由于许多消息传递系统中用于存储的数据结构的规模很小,所以这也是一个务实的选择——因为代理知道消耗了什么,所以可以立即删除它,从而保持数据的小规模。
可能不太明显的是,让代理和消费者就所消费的内容达成一致并不是一个简单的问题。如果代理在每次通过网络分发消息时都将其立即记录为已使用的消息,那么如果使用者未能处理该消息(例如因为它崩溃或请求超时或其他原因),则该消息将丢失。为了解决这个问题,许多消息传递系统添加了一个确认功能,这意味着消息只在发送时被标记为已发送而不是已使用;代理等待来自使用者的特定确认,以便在使用消息时记录消息。这种策略解决了丢失消息的问题,但也产生了新的问题。首先,如果使用者处理消息,但在发送确认之前失败,则该消息将被使用两次。第二个问题是关于性能的,现在代理必须为每条消息保留多个状态(首先锁定它,这样它就不会第二次发出,然后将其标记为永久使用过的,这样就可以删除它)。必须处理棘手的问题,比如如何处理发送但从未被确认的消息。
Kafka以不同的方式处理这个问题。我们的主题被划分为一组完全有序的分区,每个分区在任何给定时间都由每个订阅用户组中的一个用户使用。这意味着消费者在每个分区中的位置只是一个整数,即下一个要消费的消息的偏移量。这使得消耗的状态非常小,每个分区只有一个数字。这种状态可以定期检查。这使得等价的消息确认非常便宜。
这个决定还有一个好处。使用者可以有意地倒回旧的偏移量并重新使用数据。这违反了队列的公共契约,但实际上是许多消费者的一个基本特性。例如,如果使用者代码有一个错误,并且在使用了一些消息之后发现了它,那么一旦错误被修复,使用者就可以重新使用这些消息。
Offline Data Load(脱机数据加载)
可伸缩持久性允许只定期消费批处理数据加载(批处理数据加载会定期将数据批量加载到离线系统,如Hadoop或关系数据仓库)的消费者。
在Hadoop的情况下,我们通过将负载拆分到各个map任务(每个节点/主题/分区组合对应一个映射任务)来并行化数据负载,从而允许负载中的完全并行。Hadoop提供了任务管理,失败的任务可以在没有重复数据危险的情况下重新启动,只需从原始位置重新启动即可
4.6 Message Delivery Semantics(消息传递语义)
既然我们已经了解了生产者和消费者如何工作,那么让我们讨论一下Kafka在生产者和消费者之间提供的语义保证。显然,可以提供多种可能的消息传递保证:
- At most once--消息可能会丢失,但不会重新传递。
- At least once--消息不会丢失,但可以重新传递。
- Exactly once--这正是人们真正想要的,每条消息只传递一次。
值得注意的是,这分为两个问题:发布消息的持久性保证和使用消息时的保证。
许多系统声称提供“恰好一次”的交付语义,但阅读精细打印很重要,这些声明中的大多数都是误导性的(即,它们不会转化为消费者或生产者可能失败的情况、存在多个消费者进程的情况或写入磁盘的数据可能丢失的情况)。
Kafka的语义学是直截了当的。当发布消息时,我们有消息被“提交”到日志的概念。一旦提交了已发布的消息,只要复制该消息写入的分区的代理保持“活动”,该消息就不会丢失。下一节将更详细地描述提交消息的定义、活动分区以及我们试图处理的故障类型。现在,让我们假设一个完美的、无损的经纪人,并尝试理解对生产者和消费者的担保。如果生产者试图发布一条消息并经历了一个网络错误,它不能确定这个错误是在提交消息之前还是之后发生的。这类似于使用自动生成的键插入数据库表的语义。
在0.11.0.0之前,如果生产者未能接收到指示消息已提交的响应,那么它别无选择,只能重新发送消息。这至少提供了一次传递语义,因为如果原始请求确实成功了,则在重新发送期间可以再次将消息写入日志。从0.11.0.0开始,Kafka生产者还支持幂等传递选项,该选项保证重新发送不会导致日志中出现重复条目。为此,代理为每个生产者分配一个ID,并使用生产者连同每个消息一起发送的序列号来去重消息。同样从0.11.0.0开始,生产者支持使用类似事务的语义将消息发送到多个主题分区的能力:即要么所有消息都被成功编写,要么没有一条消息被成功编写。这种方法的主要用例是在Kafka主题之间进行正好一次处理(如下所述)。
并不是所有的用例都需要这样强大的保证。对于延迟敏感的应用,我们允许生产者指定它希望的持久性级别。如果生产者指定它想要等待提交的消息,这可能需要10毫秒的时间。然而,生产者也可以指定它想要完全异步地执行发送,或者它只想等到领导者(但不一定是追随者)得到消息。
现在让我们从消费者的角度来描述语义。所有副本具有完全相同的日志和偏移量。使用者控制其在此日志中的位置。如果使用者没有崩溃,它可以将这个位置存储在内存中,但是如果使用者失败,并且我们希望这个主题分区被另一个进程接管,那么新进程将需要选择一个合适的位置,从那里开始处理。假设使用者读取一些消息——它有几个选项来处理消息并更新其位置。
- 它可以读取消息,然后保存其在日志中的位置,最后处理消息。在这种情况下,使用者进程有可能在保存其位置之后但在保存其消息处理的输出之前崩溃。在这种情况下,接管处理的进程将从保存的位置开始,即使该位置之前的一些消息没有被处理。这对应于“至多一次”语义,因为在使用者失败的情况下,可能不会处理消息。
- 它可以读取消息,处理消息,最后保存其位置。在这种情况下,使用者进程有可能在处理消息之后但在保存其位置之前崩溃。在这种情况下,当新进程在接管接收到的头几条消息时,这几条消息讲已经被处理好。这对应于消费者失败情况下的“至少一次”语义。在许多情况下,消息都有一个主键,因此更新是幂等的(两次接收相同的消息只会用它自身的另一个副本覆盖一条记录)。
那么关于正好一次语义(即您真正想要的东西)又如何呢?当从一个Kafka主题消费并生成到另一个主题时(就像在Kafka Streams应用程序中一样),我们可以利用上面提到的0.11.0.0中的新的事务生产者功能。使用者的位置存储为主题中的一个消息,因此我们可以在接收处理数据的输出主题的同一事务中将偏移量写入Kafka。如果事务被中止,使用者的位置将恢复到原来的值,并且关于输出主题的生成数据对其他使用者不可见,这取决于他们的“隔离级别”。在默认的“read_uncommitted”隔离级别中,所有消息对使用者都是可见的,即使它们是中止事务的一部分,但是在“read_committed”中,使用者将只返回已提交事务的消息(以及不属于事务的任何消息)。
当写入外部系统时,限制在于需要将使用者的位置与实际存储为输出的内容进行协调。实现这一点的经典方法是在使用者位置的存储和使用者输出的存储之间引入两阶段提交。但是,这可以通过让消费者将其偏移量存储在与输出相同的位置来更简单地和更一般地处理。这更好,因为消费者可能希望写入的许多输出系统不支持两阶段提交。作为这方面的一个例子,考虑一个Kafka Connect连接器,它将数据连同它读取的数据的偏移量填充到HDFS中,这样就可以保证数据和偏移量都是更新的,或者两者都没更新。对于许多其他数据系统,我们遵循类似的模式,这些系统需要更强的语义,并且消息没有允许去重的主键。
因此,Kafka有效地支持Kafka流-- Kafka Streams中的精确一次交付,并且当在Kafka主题之间传输和处理数据时,事务生产者/消费者通常可以用来提供精确一次交付。为其他目标系统提供一次交付通常需要与此类系统协作,但是Kafka提供了实现此功能的补偿(请参阅 Kafka Connect)。否则,Kafka默认情况下保证至少一次交付,并允许用户实现最多一次交付,方法是在处理一批消息之前禁用对生产者的重试并在消费者中提交偏移量。
4.7 Replication
Kafka跨多个可配置的服务器复制每个主题分区的日志(您可以基于主题逐个设置此复制系数)。这允许在集群中的服务器发生故障时自动将故障转移到这些副本,以便在出现故障时消息仍然可用。