apache-kafka - Kafka 在创建新主题时会产生大量额外数据
问题描述
我有一个 3 节点 Zookeeper 集群版本 3.4.11 和 2 节点 Kafka 集群版本 0.11.3。我们写了一个生产者,将消息发送到 Kafka 集群的特定主题和分区(我之前做过,生产者经过测试)。以下是经纪人配置:
broker.id=1
listeners=PLAINTEXT://node1:9092
num.partitions=24
delete.topic.enable=true
default.replication.factor=2
log.dirs=/data
zookeeper.connect=zoo1:2181,zoo2:2181,zoo3:2181
log.retention.hours=168
zookeeper.session.timeout.ms=40000
zookeeper.connection.timeout.ms=10000
offsets.topic.replication.factor=2
transaction.state.log.replication.factor=2
transaction.state.log.min.isr=2
一开始,经纪人没有话题,他们会自动创建。当我启动生产者时,Kafka 集群出现了一个奇怪的行为:
1- 它创建所有主题,但生成数据的速率为每秒 10KB,在不到一分钟的时间内,每个代理的日志目录从零数据变为 9.0 GB 数据!并且所有代理都关闭了(因为缺少日志目录容量)
2-就在开始生成数据时,我尝试使用控制台消费者来消费数据,但它只是错误
WARN Error while fetching metadata with correlation id 2 : {Topic1=LEADER_NOT_AVAILABLE} (org.apache.kafka.clients.NetworkClient)
3-这是经纪人日志中反复出现的错误:
INFO Updated PartitionLeaderEpoch. New: {epoch:0, offset:0}, Current: {epoch:-1, offset-1} for Partition: Topic6-6. Cache now contains 0 entries. (kafka.server.epoch.LeaderEpochFileCache)
WARN Newly rolled segment file 00000000000000000000.log already exists; deleting it first (kafka.log.Log)
WARN Newly rolled segment file 00000000000000000000.index already exists; deleting it first (kafka.log.Log)
WARN Newly rolled segment file 00000000000000000000.timeindex already exists; deleting it first (kafka.log.Log)
ERROR [Replica Manager on Broker 1]: Error processing append operation on partition Topic6-6 (kafka.server.ReplicaManager)
kafka.common.KafkaException: Trying to roll a new log segment for topic partition Topic6-6 with start offset 0 while it already exists.
在多次重复上述日志后,我们有:
ERROR [ReplicaManager broker=1] Error processing append operation on partition Topic24-10 (kafka.server.ReplicaManager)
org.apache.kafka.common.errors.InvalidOffsetException: Attempt to append an offset (402) to position 5 no larger than the last offset appended (402)
最后(当 log-dir 中没有空间时)它会出错:
FATAL [Replica Manager on Broker 1]: Error writing to highwatermark file: (kafka.server.ReplicaManager)
java.io.FileNotFoundException: /data/replication-offset-checkpoint.tmp (No space left on device)
并关机!
4-我在另一台机器上设置了新的单节点 Kafka 版本 0.11.3,它使用相同的生产者和使用相同的 Zookeeper 集群运行良好。
5- 我关闭了两个 Kafka 代理之一,只使用一个(集群的)代理,它的行为与我使用两个节点 Kafka 集群时的行为相同。
问题是什么?
UPDATE1:我尝试了 Kafka 2.1.0 版,但结果相同!
UPDATE2:我发现了问题的根源。在制作过程中,我创建了 25 个主题,每个主题都有 24 个分区。令人惊讶的是,每个主题刚刚创建(使用 kafka-topic.sh 命令并且没有存储数据时)占用了 481MB 空间!例如,在每个分区目录的主题“20”的日志目录中,我有以下文件,总共有 21MB:
00000000000000000000.index (10MB) 00000000000000000000.log(0MB) 00000000000000000000.timeindex(10MB) leader-epoch-checkpoint(4KB)
Kafka 为 server.log 文件中的每个主题分区写入以下行:
[2019-02-05 10:10:54,957] INFO [Log partition=topic20-14, dir=/data] Loading producer state till offset 0 with message format version 2 (kafka.log.Log)
[2019-02-05 10:10:54,957] INFO [Log partition=topic20-14, dir=/data] Completed load of log with 1 segments, log start offset 0 and log end offset 0 in 1 ms (kafka.log.Log)
[2019-02-05 10:10:54,958] INFO Created log for partition topic20-14 in /data with properties {compression.type -> producer, message.format.version -> 2.1-IV2, file.delete.delay.ms -> 60000, max.message.bytes -> 1000012, min.compaction.lag.ms -> 0, message.timestamp.type -> CreateTime, message.downconversion.enable -> true, min.insync.replicas -> 1, segment.jitter.ms -> 0, preallocate -> false, min.cleanable.dirty.ratio -> 0.5, index.interval.bytes -> 4096, unclean.leader.election.enable -> false, retention.bytes -> -1, delete.retention.ms -> 86400000, cleanup.policy -> [delete], flush.ms -> 9223372036854775807, segment.ms -> 604800000, segment.bytes -> 1073741824, retention.ms -> 604800000, message.timestamp.difference.max.ms -> 9223372036854775807, segment.index.bytes -> 10485760, flush.messages -> 9223372036854775807}. (kafka.log.LogManager)
[2019-02-05 10:10:54,958] INFO [Partition topic20-14 broker=0] No checkpointed highwatermark is found for partition topic20-14 (kafka.cluster.Partition)
[2019-02-05 10:10:54,958] INFO Replica loaded for partition topic20-14 with initial high watermark 0 (kafka.cluster.Replica)
[2019-02-05 10:10:54,958] INFO [Partition topic20-14 broker=0] topic20-14 starts at Leader Epoch 0 from offset 0. Previous Leader Epoch was: -1 (kafka.cluster.Partition)
服务器日志上没有错误。如果我生成有关该主题的数据,我什至可以使用数据。由于总日志目录空间为 10GB,Kafka 在我的场景中需要 12025MB 用于 25 个主题,这大于总目录空间,Kafka 会出错并关闭!
只是为了测试,我使用相同的 Zookeeper 集群设置了另一个 Kafka 代理(即 broker2),并在那里创建了一个有 24 个分区的新主题,所有空分区只占用 100K!
所以我真的很困惑!Broker1 和 Broker2,相同版本的 Kafka (0.11.3) 正在运行,只是操作系统和系统文件不同:
以 Broker1 为例(新主题占用 481MB 数据):
- OS CentOS 7 和 XFS 作为系统文件
以 Broker2 为例(新主题占用 100KB 数据):
- OS Ubuntu 16.04 和 ext4 作为系统文件
解决方案
- 为什么 Kafka 为每个分区预分配 21MB?
这是正常行为,索引的预分配大小是使用服务器属性控制的:segment.index.bytes
默认值为 10485760 字节或 10MB。这是因为每个分区目录中的索引分配了 10MB:
00000000000000000000.index (10MB)
00000000000000000000.log(0MB)
00000000000000000000.timeindex(10MB)
leader-epoch-checkpoint(4KB)
另一方面,Kafka 文档中提到了该属性:
We preallocate this index file and shrink it only after log rolls.
但就我而言,它从未缩小指数。经过大量搜索后,我发现某些版本的 Java 8(在我的情况下为 192)在处理许多小文件时存在错误,并且已在更新 202 中修复。所以我将我的 Java 版本更新为 202,它解决了这个问题。
推荐阅读
- react-native - react-native-elements 的表单组件导致“不变违规”错误
- angular - 如何在Angular中检查此数据中是否存在用户名?
- express - 使用 JWT——在服务器端有没有办法检查用户当前是否登录?
- c++ - 在 C++ 中编码解码的 url
- excel - 如何通过条件VBA从范围中选择一个随机值
- flutter - 如何正确填充具有点击效果的 IconButton?
- javascript - 如何模拟节点readline?
- javascript - 单击AJAX时如何显示所选选项标签的值
- spring-boot - Spring Lemon:缺少响应标头 Set-Cookie 和 X-XSRF-TOKEN
- rust - 如何向编译器传达借用仅发生在枚举的一半中