Kafka Broker抵消/日志保留和使用者抵消最早的重置方式

时间:2018-12-19 12:17:05

标签: java spring-boot apache-kafka spring-cloud-stream

问题描述:

我们的Kafka使用者(在Spring Boot 2.x中开发)正在执行几天。 重新启动这些使用者时,将再次使用该主题的所有消息,但仅在特定条件下使用。

条件:

我们假设代理/主题配置( log.retention。* offsets.retention。* )和使用者配置( auto.offset)组合在一起。重置 = 最早)导致此行为。
显然,我们不能将使用者设置为“最新” ,因为如果使用者停止并且新消息到达,则当使用者再次启动时,这些消息将不会被使用。

问题:

为避免这种情况的正确设置是什么?
在最新的Kafka Broker版本(2.x)中,log.retention。*和offsets.retention。*的默认值相同(https://cwiki.apache.org/confluence/display/KAFKA/KIP-186%3A+Increase+offsets+retention+default+to+7+days

这种新的配置设置可以解决问题吗?

消费者配置(在Spring Cloud Stream Framework上委派的 auto.commit ):

           auto.commit.interval.ms = 100
           auto.offset.reset = earliest
           bootstrap.servers = [server1:9092]
           check.crcs = true
           client.id = 
           connections.max.idle.ms = 540000
           enable.auto.commit = false
           exclude.internal.topics = true
           fetch.max.bytes = 52428800
           fetch.max.wait.ms = 500
           fetch.min.bytes = 1
           group.id = consumer_group1
           heartbeat.interval.ms = 3000
           interceptor.classes = null
           internal.leave.group.on.close = true
           isolation.level = read_uncommitted
           key.deserializer = class org.apache.kafka.common.serialization.ByteArrayDeserializer
           max.partition.fetch.bytes = 1048576
           max.poll.interval.ms = 300000
           max.poll.records = 500
           metadata.max.age.ms = 300000
           metrics.recording.level = INFO
           metrics.sample.window.ms = 30000
           partition.assignment.strategy = [class org.apache.kafka.clients.consumer.RangeAssignor]
           receive.buffer.bytes = 65536
           reconnect.backoff.max.ms = 1000
           reconnect.backoff.ms = 50
           request.timeout.ms = 305000
           retry.backoff.ms = 100
           value.deserializer = class org.apache.kafka.common.serialization.ByteArrayDeserializer

经纪人配置:

           log.retention.ms = 86400000
           log.retention.minutes = 10080
           log.retention.hours = 168
           log.retention.bytes = -1

           offsets.retention.ms = 864000000
           offsets.retention.minutes = 14400
           offsets.retention.hours = 240 

           unclean.leader.election.enable = false
           log.cleaner.enable = true
           auto.leader.rebalance.enable = true
           leader.imbalance.check.interval.seconds = 300
           log.retention.check.interval.ms = 300000
           log.cleaner.delete.retention.ms = 604800000

感谢和问候

2 个答案:

答案 0 :(得分:1)

是的,由于2.0之前的Kafka版本的log.retention.*offsets.retention.*(分别为7天和1天)的值不同,您遇到了此问题,请检查description here。 这是因为您的主题中出现了罕见的消息,并且抵消数据已经过期。

关于您的短语Obviously we can't set consumer to "latest"并不完全正确。 如果您在不到1天前(例如前几个小时)收到了最后一条消息,则可以安全地将auto.offset.reset的值更新为latest,并且使用相同的组ID(或application.id)。在这种情况下,您不会丢失消息。

作为另一种选择,您可以将特定主题的日志保留值更改为1天。 另外,您可以更新值offsets.retention.*,但是您需要从性能角度对其进行测试,否则它可能会降级。

答案 1 :(得分:0)

如果您使应用程序保持24x7全天候运行(例如,在没有数据的周末),则一种选择是设置idleInterval并添加ApplicationListener(或@EventListener)收听ListenerContainerIdleEvent

然后,如果idleTime属性接近日志保留,则可以在事件中使用Consumer重新提交偏移量-获取分配的分区,找到其当前的position()然后重新提交。