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

时间:2018-07-11 10:57:04

标签: java apache-kafka

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

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

是否存在实际上从硬盘驱动器中删除记录的Java API?

6 个答案:

答案 0 :(得分:2)

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

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

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

紧凑 如果确实需要数据永久保存或至少保留很长时间,但是只需要 latest 值,则可以将主题设置为紧凑。添加带有已存在密钥的新消息后,这将自动删除较旧的消息。

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

答案 1 :(得分:1)

起初这也让我有些困惑,为什么包含的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();

答案 2 :(得分:1)

我在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的答案。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

我可以删除。如果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);
}