重新平衡后,kafka 停止使用来自新分配分区的消息
kafka stop consuming message from new assigned partitions after rebalancing
我对 kafka 很陌生(对英语也很陌生...),我遇到了这个问题,无法 google 任何解决方案。
我使用 spring-boot,spring-kafka 支持,我在我的本地机器上安装了 kafka_2.11-0.10.1.1(只有一个 broker 0)
s1.then 我创建话题
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 5 --topic tracking
我的消费者配置:
applitions.properties:
kafka.servers.bootstrap=localhost:9092
kafka.topic.tracking=tracking
kafka.group.id=trackingGroup
kafka.client.id=client-1
s2。然后我通过更改 'kafka.client.id' 和 运行 spring-boot main class 启动 3 个消费者。在 Eclipse 控制台上,我可以检查分区分配:
client-1: partitions assigned:[tracking-4, tracking-3]
client-2: partitions assigned:[tracking-2, tracking-1]
client-3: partitions assigned:[tracking-0]
s3。启动pruducer向topic发送20条消息,每条开始消费特定partition
的消息
s4。我关闭消费 1,kafka 自动进行重新平衡,
新分区分配:
client-1: partitions assigned:[]
client-2: partitions assigned:[tracking-2,tracking-1, tracking-0]
client-3: partitions assigned:[tracking-4,tracking-3]
s5。我发现分区 'tracking-3' 上的消息没有被消耗 !!
问题每次都会重现,在新分配的分区丢失一些消息,你有什么建议吗?请帮助我,谢谢
我转载了;重新平衡时,kafka 本身(auto.comit.enabled=true
)似乎有问题,kafka 报告未读分区(the offset of the <i>next record</i> that will be fetched (if a record with that offset exists)
)的 "position" 作为分区的末尾。
其实我在使用kafka-consumer-groups工具的时候,未读分区的偏移量已经在"end"处了。当我 运行 它只有一个消费者时,当它正在读取第一个分区时,我看到...
$ kafka-consumer-groups --bootstrap-server localhost:9092 --describe -group so43405009
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 37 40 3 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 1 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 2 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 3 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 4 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
注意 CURRENT_OFFSET 列。
在下一个 运行 上,我 运行 两次,一次是在处理第一个分区时,稍后再一次...
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 41 44 3 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 1 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 2 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 3 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 4 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
和
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 1 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 2 41 44 3 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 3 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 4 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
查看分区 2 的当前偏移量如何从 44 下降到 41。
禁用自动提交为我解决了问题...
spring.kafka.consumer.enable-auto-commit=false
...
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 52 52 0 client1-59413599-81e8-49dd-bbd7-8a62152f11e5 /10.0.0.6 client1
tracking 1 49 52 3 client1-59413599-81e8-49dd-bbd7-8a62152f11e5 /10.0.0.6 client1
tracking 2 49 52 3 client2-edfe34f9-08d5-4825-80d0-4a6cf9526e42 /10.0.0.6 client2
tracking 3 48 52 4 client2-edfe34f9-08d5-4825-80d0-4a6cf9526e42 /10.0.0.6 client2
tracking 4 51 52 1 client3-20da8742-af38-403e-b125-5d0c7c771319 /10.0.0.6 client3
这是我的测试程序:
@SpringBootApplication
public class So43405009Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(So43405009Application.class, args);
}
@Autowired
private KafkaTemplate<String, String> template;
@Value("${spring.kafka.consumer.client-id}")
private String clientId;
@Override
public void run(String... args) throws Exception {
if (this.clientId.endsWith("1")) {
for (int i = 0; i < 20; i++) {
this.template.sendDefault("foo" + i);
}
}
}
@Bean
public KafkaMessageListenerContainer<String, String> container(ConsumerFactory<String, String> cf) {
ContainerProperties containerProperties = new ContainerProperties("tracking");
containerProperties.setMessageListener((MessageListener<?, ?>) d -> {
System.out.println(d);
try {
Thread.sleep(5_000);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
KafkaMessageListenerContainer<String, String> container = new KafkaMessageListenerContainer<>(cf,
containerProperties);
return container;
}
}
具有属性
spring.kafka.listener.ack-mode=record
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.group-id=so43405009
spring.kafka.consumer.client-id=client1
spring.kafka.template.default-topic=tracking
我在 0.10.2.0 上也看到了同样的结果。
编辑
原来是spring-kafka的bug;它在启用自动提交的情况下工作,但你必须明确启用它
spring.kafka.consumer.enable-auto-commit=true
否则容器假定它是 false
并导致上述 st运行ge 行为 - 看起来客户端不喜欢在启用自动提交的情况下调用消费者的提交方法。 #288.
我通常建议设置为 false,并选择容器的 AckMode
之一;例如RECORD
在每次记录后提交,BATCH
在轮询收到每个批次后提交(默认)。
我对 kafka 很陌生(对英语也很陌生...),我遇到了这个问题,无法 google 任何解决方案。
我使用 spring-boot,spring-kafka 支持,我在我的本地机器上安装了 kafka_2.11-0.10.1.1(只有一个 broker 0)
s1.then 我创建话题
bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 5 --topic tracking
我的消费者配置: applitions.properties:
kafka.servers.bootstrap=localhost:9092
kafka.topic.tracking=tracking
kafka.group.id=trackingGroup
kafka.client.id=client-1
s2。然后我通过更改 'kafka.client.id' 和 运行 spring-boot main class 启动 3 个消费者。在 Eclipse 控制台上,我可以检查分区分配:
client-1: partitions assigned:[tracking-4, tracking-3]
client-2: partitions assigned:[tracking-2, tracking-1]
client-3: partitions assigned:[tracking-0]
s3。启动pruducer向topic发送20条消息,每条开始消费特定partition
的消息s4。我关闭消费 1,kafka 自动进行重新平衡, 新分区分配:
client-1: partitions assigned:[]
client-2: partitions assigned:[tracking-2,tracking-1, tracking-0]
client-3: partitions assigned:[tracking-4,tracking-3]
s5。我发现分区 'tracking-3' 上的消息没有被消耗 !!
问题每次都会重现,在新分配的分区丢失一些消息,你有什么建议吗?请帮助我,谢谢
我转载了;重新平衡时,kafka 本身(auto.comit.enabled=true
)似乎有问题,kafka 报告未读分区(the offset of the <i>next record</i> that will be fetched (if a record with that offset exists)
)的 "position" 作为分区的末尾。
其实我在使用kafka-consumer-groups工具的时候,未读分区的偏移量已经在"end"处了。当我 运行 它只有一个消费者时,当它正在读取第一个分区时,我看到...
$ kafka-consumer-groups --bootstrap-server localhost:9092 --describe -group so43405009
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 37 40 3 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 1 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 2 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 3 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
tracking 4 40 40 0 client1-8129bb3d-3a83-4c83-9128-3a2762ede758 /10.0.0.6 client1
注意 CURRENT_OFFSET 列。
在下一个 运行 上,我 运行 两次,一次是在处理第一个分区时,稍后再一次...
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 41 44 3 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 1 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 2 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 3 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 4 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
和
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 1 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 2 41 44 3 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 3 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
tracking 4 44 44 0 client1-56d78a4b-f2df-4e31-8c5d-f8a1d8f64cf8 /10.0.0.6 client1
查看分区 2 的当前偏移量如何从 44 下降到 41。
禁用自动提交为我解决了问题...
spring.kafka.consumer.enable-auto-commit=false
...
TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID
tracking 0 52 52 0 client1-59413599-81e8-49dd-bbd7-8a62152f11e5 /10.0.0.6 client1
tracking 1 49 52 3 client1-59413599-81e8-49dd-bbd7-8a62152f11e5 /10.0.0.6 client1
tracking 2 49 52 3 client2-edfe34f9-08d5-4825-80d0-4a6cf9526e42 /10.0.0.6 client2
tracking 3 48 52 4 client2-edfe34f9-08d5-4825-80d0-4a6cf9526e42 /10.0.0.6 client2
tracking 4 51 52 1 client3-20da8742-af38-403e-b125-5d0c7c771319 /10.0.0.6 client3
这是我的测试程序:
@SpringBootApplication
public class So43405009Application implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(So43405009Application.class, args);
}
@Autowired
private KafkaTemplate<String, String> template;
@Value("${spring.kafka.consumer.client-id}")
private String clientId;
@Override
public void run(String... args) throws Exception {
if (this.clientId.endsWith("1")) {
for (int i = 0; i < 20; i++) {
this.template.sendDefault("foo" + i);
}
}
}
@Bean
public KafkaMessageListenerContainer<String, String> container(ConsumerFactory<String, String> cf) {
ContainerProperties containerProperties = new ContainerProperties("tracking");
containerProperties.setMessageListener((MessageListener<?, ?>) d -> {
System.out.println(d);
try {
Thread.sleep(5_000);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
KafkaMessageListenerContainer<String, String> container = new KafkaMessageListenerContainer<>(cf,
containerProperties);
return container;
}
}
具有属性
spring.kafka.listener.ack-mode=record
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.group-id=so43405009
spring.kafka.consumer.client-id=client1
spring.kafka.template.default-topic=tracking
我在 0.10.2.0 上也看到了同样的结果。
编辑
原来是spring-kafka的bug;它在启用自动提交的情况下工作,但你必须明确启用它
spring.kafka.consumer.enable-auto-commit=true
否则容器假定它是 false
并导致上述 st运行ge 行为 - 看起来客户端不喜欢在启用自动提交的情况下调用消费者的提交方法。 #288.
我通常建议设置为 false,并选择容器的 AckMode
之一;例如RECORD
在每次记录后提交,BATCH
在轮询收到每个批次后提交(默认)。