调用deleteRecords Kafka Admin Client Java API时,不会从文件系统中删除消息。

时间:2019-06-25 20:55:14

标签: java apache-kafka

我试图使用Java Admin Client API的delete Records方法从kafka主题中删除消息。以下是我尝试过的步骤


    1. I pushed 20000 records to my TEST-DELETE topic
    2. Started a console consumer and consumed all the messages
    3. Invoked my java program to delete all those 20k messages
    4. Started another console consumer with a different group id. This consumer is not receiving any of the deleted messages

当我检查文件系统时,我仍然可以看到所有20k条记录都占用了磁盘空间。我的意图是也从文件系统中永久删除这些记录。

我的主题配置以及server.properties设置在下面给出


Topic:TEST-DELETE       PartitionCount:4        ReplicationFactor:1     Configs:cleanup.policy=delete
        Topic: TEST-DELETE    Partition: 0      Leader: 0     Replicas: 0       Isr: 0
        Topic: TEST-DELETE    Partition: 1      Leader: 0     Replicas: 0       Isr: 0
        Topic: TEST-DELETE    Partition: 2      Leader: 0     Replicas: 0       Isr: 0
        Topic: TEST-DELETE    Partition: 3      Leader: 0     Replicas: 0       Isr: 0


    log.retention.hours=24
    log.retention.check.interval.ms=60000
    log.cleaner.delete.retention.ms=60000
    file.delete.delay.ms=60000
    delete.retention.ms=60000
    offsets.retention.minutes=5
    offsets.retention.check.interval.ms=60000
    log.cleaner.enable=true
    log.cleanup.policy=compact,delete

我的删除代码在下面给出


public void deleteRecords(Map<String, Map<Integer, Long>> allTopicPartions) {

        Map<TopicPartition, RecordsToDelete> recordsToDelete = new HashMap<>();

        allTopicPartions.entrySet().forEach(topicDetails -> {

            String topicName = topicDetails.getKey();
            Map<Integer, Long> value = topicDetails.getValue();

            value.entrySet().forEach(partitionDetails -> {

                if (partitionDetails.getValue() != 0) {
                    recordsToDelete.put(new TopicPartition(topicName, partitionDetails.getKey()),
                            RecordsToDelete.beforeOffset(partitionDetails.getValue()));
                }
            });
        });

        DeleteRecordsResult deleteRecords = this.client.deleteRecords(recordsToDelete);

        Map<TopicPartition, KafkaFuture<DeletedRecords>> lowWatermarks = deleteRecords.lowWatermarks();

        lowWatermarks.entrySet().forEach(entry -> {
            try {
                logger.info(entry.getKey().topic() + " " + entry.getKey().partition() + " "
                        + entry.getValue().get().lowWatermark());
            } catch (Exception ex) {

            }
        });

    }

下面是我的Java程序的输出



2019-06-25 16:21:15 INFO  MyKafkaAdminClient:247 - TEST-DELETE 1 5000
2019-06-25 16:21:15 INFO  MyKafkaAdminClient:247 - TEST-DELETE 0 5000
2019-06-25 16:21:15 INFO  MyKafkaAdminClient:247 - TEST-DELETE 3 5000
2019-06-25 16:21:15 INFO  MyKafkaAdminClient:247 - TEST-DELETE 2 5000

我的打算是从文件系统中删除消耗的记录,因为我正在为我的kafka代理使用有限的存储空间。

我想从下面的疑惑中寻求帮助

  1. 我的印象是,删除记录也会从文件系统中删除消息,但看起来我弄错了!!
  2. 这些已删除的记录在日志目录中存在多长时间?
  3. 调用delete Records API后,是否需要使用任何特定配置才能从文件系统中删除记录?

感谢您的帮助

谢谢

1 个答案:

答案 0 :(得分:0)

处理此问题的推荐方法是为感兴趣的主题设置retention.ms和相关的配置值。这样,您可以定义Kafka在删除数据之前将存储数据的时间,确保您所有的下游消费者都有机会先将数据拉出,然后再将其从Kafk集群中删除。

但是,如果您仍然要强制Kafka根据字节删除,则有log.retention.bytesretention.bytes配置值。第一个是群集范围的设置,第二个是特定于主题的设置,默认情况下,它采用第一个设置为的设置,但是您仍然可以按每个主题覆盖它。 retention.bytes号是每个分区强制执行的,因此您应将其乘以主题分区的总数。

但是请注意,如果您有一个失控的生产者突然开始生成大量数据,并且将其设置为硬字节限制,则可能会消灭集群中整天的数据,并且只剩下最后几分钟的数据,甚至在有效的使用者都无法从群集中提取数据之前。这就是为什么最好将您的kafka主题设置为基于时间的保留,而不是基于字节的保留。

您可以在Kafka官方文档中找到配置属性及其说明:https://kafka.apache.org/documentation/