事务性生产者与Java幂等生产者(OutOfOrderSequenceException异常)

时间:2019-03-16 02:21:01

标签: java apache-kafka kafka-producer-api spring-kafka

我将spring-kafka用于幂等生产者配置:

这些是我的配置道具:

   Properties props = new Properties();
    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, Joiner.on(",").join(appProps.getBrokers()));
    //configure the following three settings for SSL Encryption
    props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, "SSL");
    props.put(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG, appProps.getJksLocation());
    props.put(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG,  appProps.getJksPassword());
    props.put(ProducerConfig.ACKS_CONFIG, "all");
    props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG,true);
    props.put(ProducerConfig.RETRIES_CONFIG, 5);
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");

我的卡夫卡生产者抛出OutOfOrderSequenceException:

  

2019-03-06 21:25:47发件人[错误] [生产者clientId = producer-1]经纪人返回org.apache.kafka.common.errors.OutOfOrderSequenceException:经纪人收到了以下订单的无序序列号topic-partition topic-1,位于偏移-1处。这表明代理上的数据丢失,应进行调查。     2019-03-06 21:25:47 TransactionManager [INFO] [生产者clientId = producer-1]在时期-1时将ProducerId设置为-1     2019-03-06 21:25:47 ProducerKafka [错误]发送到kafka时遇到错误,请重试作业

我不确定为什么会引发此异常。我找不到对此的具体答案。异常的官方javadoc声明以下内容:

  

此异常表明代理从生产者接收到意外的序列号,这意味着数据可能已丢失。如果生产者仅配置为幂等(即,如果设置了enable.idempotence并且未配置transactional.id),则可以继续使用同一生产者实例进行发送,但是这样做可能会重新排序已发送记录的顺序。对于事务性生产者,这是一个致命错误,您应该关闭生产者。

这是否意味着我需要使用事务性生产者来避免此问题?

KafkaProducer文档说明了使上述说法含糊的内容:https://kafka.apache.org/0110/javadoc/index.html?org/apache/kafka/clients/producer/KafkaProducer.html

  

要启用等幂,必须将enable.idempotence配置设置为true。如果设置,则重试配置将默认为Integer.MAX_VALUE,max.in.flight.requests.per.connection配置将默认为1,而acks配置将默认为all。幂等生产者没有API更改,因此无需修改现有应用程序即可利用此功能。

     

要利用幂等生成器,必须避免重新发送应用程序级别,因为这些应用程序无法重复删除。因此,如果应用程序启用幂等性,建议将重试配置保留为未设置状态,因为它将默认为Integer.MAX_VALUE。此外,如果send(ProducerRecord)即使无限次重试也返回错误(例如,如果消息在发送之前已在缓冲区中过期),则建议关闭生产者并检查最后产生的消息的内容,以确保不能重复。最后,生产者只能保证在单个会话中发送的消息具有幂等性。

上面的声明清楚地表明,我需要一个幂等生成器,只是使用enable.idempotence属性。但是,该异常指出我必须使用该transactional.id属性。

创建幂等异步生成器而不必处理致命的OutOfOrderSequenceException的正确方法是什么。

2 个答案:

答案 0 :(得分:0)

对我来说似乎很清楚;从第二个报价...

  

要利用幂等生成器,必须避免重新发送应用程序级别,因为这些应用程序无法重复删除。因此,如果应用程序启用幂等性,建议将重试配置保留为未设置状态,因为它将默认为Integer.MAX_VALUE。

你有

props.put(ProducerConfig.RETRIES_CONFIG, 5);

答案 1 :(得分:0)

如果您明确设置了重试次数,那么您必须设置

max.in.flight.requests.per.connection=1

为了避免乱序问题

该文档非常清楚地说明:

设置一个大于零的值将导致客户端重新发送任何发送失败并可能出现暂时性错误的记录。请注意,此重试与客户端在收到错误后重新发送记录的情况没有什么不同。 允许重试而不将 MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION 设置为 1 可能会更改记录的顺序,因为如果将两个批次发送到单个分区,并且第一个失败并重试但第二个成功,则第二个批次中的记录可能首先出现。