[英]How to avoid losing messages with Kafka streams
我们有一个流应用程序,它使用来自源主题的消息,进行一些处理并将结果转发到目标主题。
消息的结构由一些 avro 模式控制。
如果模式尚未缓存,则在开始使用消息时,应用程序将尝试从模式注册表中检索它。 如果由于某种原因模式注册表不可用(比如网络故障),则当前正在处理的消息将丢失,因为默认处理程序是名为LogAndContinueExceptionHandler
的东西。
o.a.k.s.e.LogAndContinueExceptionHandler : Exception caught during Deserialization, taskId: 1_5, topic: my.topic.v1, partition: 5, offset: 142768
org.apache.kafka.common.errors.SerializationException: Error retrieving Avro schema for id 62
Caused by: java.net.SocketTimeoutException: connect timed out
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
...
o.a.k.s.p.internals.RecordDeserializer : stream-thread [my-app-StreamThread-3] task [1_5] Skipping record due to deserialization error. topic=[my.topic.v1] partition=[5] offset=[142768]
...
所以我的问题是处理上述情况的正确方法是什么,并确保无论如何都不会丢失消息。 是否有开箱即用的LogAndRollbackExceptionHandler
错误处理程序或实现您自己的方法?
预先感谢您的意见。
我在 Kafka 上工作不多,但是当我这样做时,我记得遇到了诸如您在我们的系统中描述的问题。
让我告诉你我们如何处理我们的场景,也许它也会帮助你:
场景一:如果你的消息在发布端(publisher --> kafka)丢失了,你可以根据需要配置Kafka的确认设置,如果你使用spring cloud stream和kafka,属性是spring.cloud.stream。 kafka.binder.required-acks
可能的值:
最多一次 (Ack=0)
至少一次(Ack=1)
如果 Kafka 不确认,则发布者重新发送消息。
可能的重复。
在将消息复制到副本之前发送确认。
恰好一次(Ack=all)
如果 Kafka 不确认,则发布者重新发送消息。
但是,如果一条消息多次发送到 Kafka,则不会出现重复。
内部序列号,用于决定消息是否已经写在主题上。
需要设置 Min.insync.replicas 属性以确保在 kafka 向生产者确认之前需要同步的最小副本数是多少。
场景二:如果你的数据在消费者端(kafka --> consumer)丢失了,你可以根据你的使用情况改变Kafka的Auto Commit特性。 如果您使用的是 Spring 云流spring.cloud.stream.kafka.bindings.input.consumer.AutoCommitOffset ,则这是该属性。
默认情况下,kafka 中 AutoCommitOffset 为 true,发送给消费者的每条消息都在 Kafka 端“提交”,这意味着它不会再次发送。 但是,如果您将 AutoCommitOffset 更改为 false,您将有权在代码中轮询来自 kafka 的消息,并且一旦您完成工作,明确将 commit 设置为 true,让 kafka 知道您现在已经完成了消息。
如果一条消息未提交,kafka 将继续重新发送它,直到它提交为止。
希望这可以帮助您,或者至少为您指明正确的方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.