繁体   English   中英

Kafka:如何使用 Java API 从主题中删除记录?

[英]Kafka: How to delete records from a topic using Java API?

我正在寻找一种从 Kafka 主题中删除(完全删除)消耗的记录的方法。 我知道有几种方法可以做到这一点,例如,通过更改主题的保留时间或删除 Kafka-logs 文件夹。 但我正在寻找的是一种使用 Java API 删除主题的一定数量记录的方法,如果可能的话。

我试过测试 AdminClient API,特别是adminclient.deleteRecords(recordsToDelete)方法。 但如果我没记错的话,该方法只会更改主题中的偏移量,而不会真正从硬盘驱动器中删除所述记录。

是否有 Java API 确实从硬盘驱动器中删除了记录?

Kafka主题是不变的,这意味着您只能向它们添加新消息。 本身没有删除。

但是,为了避免“磁盘用完”,Kafka提供了两个概念来减小主题的大小:保留策略和压缩。

保留如果您有一个永远不需要数据的主题,则只需设置一个保留策略,即需要多长时间(即72小时)即可。 然后,Kafka将自动为您删除超过72小时的邮件。

压缩如果确实需要数据永久保存或至少保留很长时间,但是只需要最新值,则可以将主题设置为压缩。 一旦使用已存在的密钥添加新消息,此操作将自动删除较旧的消息。

规划Kafka体系结构的中心部分是仔细考虑如何将数据存储在主题中。 例如,如果您在kafka主题中将更新推送到客户记录,假设客户的上次登录日期(非常人为的例子...),那么您仅对LAST条目感兴趣(因为所有以前的条目都不是)更长的“上次”登录时间)。 如果为此的分区键是客户ID,并且启用了日志压缩功能,则一旦用户登录并且kafka主题收到此事件,具有相同分区键(客户ID)的所有其他先前消息将被自动删除。从主题。

起初这也让我有些困惑,为什么包含的bin / kafka-delete-records.sh可以删除但我无法使用Java API

缺少的部分是您需要调用KafkaFuture.get(),因为deleteRecords返回了期货地图

这是代码

在此代码中,您需要调用entry.getValue().get().lowWatermark()

DeleteRecordsResult result = adminClient.deleteRecords(recordsToDelete);
Map<TopicPartition, KafkaFuture<DeletedRecords>> lowWatermarks = result.lowWatermarks();
try {
    for (Map.Entry<TopicPartition, KafkaFuture<DeletedRecords>> entry : lowWatermarks.entrySet()) {
        System.out.println(entry.getKey().topic() + " " + entry.getKey().partition() + " " + entry.getValue().get().lowWatermark());
    }
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
adminClient.close();

我在 Red Hat 7.6 上使用 Kafka 2.1.1,对AdminClient.deleteRecords()的调用确实有效地从 /tmp/kafka-logs 中的相应文件夹中删除了文件。 剩下的唯一文件是 leader-epoch-checkpoint,里面有关于最后记录偏移量的信息:在我的例子中是 96。

请注意,在调用AdminClient.deleteRecords()时,您不应传递大于分区现有高水位线的偏移量。 如果这样做,调用将失败并显示"org.apache.kafka.common.errors.OffsetOutOfRangeException: The requested offset is not within the range of offsets maintained by the server." 但您不会知道,直到您尝试通过Future.get()检查结果 - 有关详细信息,请参阅 Trix 的答案。

Kafka不支持从主题中删除记录。 它的工作方式是建立一个消息缓冲区,该消息缓冲区随着消息被推送到消息缓冲区而增长。 而读取消息的客户端基本上只保留该缓冲区的偏移量。 因此,Kafka中的客户端基本上处于“只读”模式,无法更改缓冲区。 考虑几个不同的客户端(不同的客户端组)读取相同主题并各自保存自己的偏移量的情况。 如果有人将开始从设置偏移量的缓冲区中删除消息,将会发生什么情况。

没有Kafka不提供删除主题中特定偏移量的功能,并且对此没有API。

我可以删除。 如果linux在计算机上,则将其从hdd中删除。 当我从互联网上搜索时,我发现Windows中存在错误。 但是,我在Windows中找不到该错误的解决方案。 如果kafka在Linux机器上运行,则此代码有效。

public void deleteMessages(String topicName, int partitionIndex, int beforeIndex) {
       TopicPartition topicPartition = new TopicPartition(topicName, partitionIndex);
       Map<TopicPartition, RecordsToDelete> deleteMap = new HashMap<>();
       deleteMap.put(topicPartition, RecordsToDelete.beforeOffset(beforeIndex));
       kafkaAdminClient.deleteRecords(deleteMap);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM