如何删除消费者已经消费的数据?卡夫卡

时间:2018-10-24 05:42:40

标签: java apache-kafka offset kafka-topic

我正在用kafka做数据复制。但是,kafka日志文件的大小增长非常快。大小一天达到5 GB。作为此问题的解决方案,我想立即删除已处理的数据。我在AdminClient中使用删除记录方法来删除偏移量。但是当我查看日志文件时,对应于该偏移量的数据不会被删除。

RecordsToDelete recordsToDelete = RedcordsToDelete.beforeOffset(offset);
TopicPartition topicPartition = new TopicPartition(topicName,partition);
Map<TopicPartition,RecordsToDelete> deleteConf = new HashMap<>();
deleteConf.put(topicPartition,recordsToDelete);
adminClient.deleteRecords(deleteConf);

我不想要像(log.retention.hours,log.retention.bytes,log.segment.bytes,log.cleanup.policy = delete)之类的建议

因为我只想删除使用者消耗的数据。在此解决方案中,我还删除了未使用的数据。

您有什么建议?

2 个答案:

答案 0 :(得分:1)

您没有做错任何事情。您提供的代码有效,我已经对其进行了测试。万一我忽略了您代码中的某些内容,我的是:

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);
}

我使用的组:“ org.apache.kafka”,名称:“ kafka-clients”,版本:“ 2.0.0”

因此请检查您是否定位到正确的分区(第一个分区为0)

检查您的经纪人版本:https://kafka.apache.org/20/javadoc/index.html?org/apache/kafka/clients/admin/AdminClient.html说:

  

0.11.0.0版的代理支持此操作

从同一应用程序产生消息,以确保您已正确连接。

您可以考虑另外一种选择。使用 cleanup.policy = compact 如果消息密钥在重复,您可以从中受益。不仅因为该密钥的旧消息将被自动删除,而且您可以使用以下事实:有效载荷为空的消息会删除该密钥的所有消息。只是不要忘记将 delete.retention.ms min.compaction.lag.ms 设置为足够小的值。在那种情况下,您可以使用一条消息,而不是为同一密钥产生空有效负载(但是请谨慎使用此方法,因为这样可以删除未使用的消息(使用该密钥)

答案 1 :(得分:1)

尝试一下

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();

在此代码中,您需要调用entry.getValue().get().lowWatermark(),因为adminClient.deleteRecords(recordsToDelete)返回了Future的映射,因此您需要通过调用get()等待Future运行。