kafka流即使在完全启用一次之后也获得重复记录

时间:2019-07-13 19:39:15

标签: kafka-consumer-api apache-kafka-streams kafka-producer-api

我正在使用kafka流接收一些数据,我注意到它获得的记录多于我发送的记录,以下是我在消费者上的设置

在消费者处

        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "streams-user-process");
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, kafkaSettigs.getKafkaBroker());
        props.put(StreamsConfig.NUM_STREAM_THREADS_CONFIG, kafkaSettigs.getTotalStreamTHreadCounnt());
        props.put(StreamsConfig.PROCESSING_GUARANTEE_CONFIG, StreamsConfig.EXACTLY_ONCE);
        props.put("isolation.level", "read_committed");
        props.put("enable.auto.commit", "true");
        props.put("auto.commit.interval.ms", "600");
        props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
       props.put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, 2000);

生产者侧的道具

Propertiesprops=newProperties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"mybootstarpservers");
props.put(ProducerConfig.CLIENT_ID_CONFIG,"clientnoveluser");

props.put(ProducerConfig.ACKS_CONFIG,"all");
props.put(ProducerConfig.RETRIES_CONFIG,3);
props.put(ProducerConfig.BATCH_SIZE_CONFIG,1500))
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,(newGenericSerializer<MyPojo>()).getClass().getName());
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
props.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,MyRandom.class);

下面是我的生产者代码

public void producerSendData(String key, MyPojo message) throws Exception {

        final Producer<String, MyPojo s> producer =  myProducerInstance.createProducer();
        final ProducerRecord<String, MyPojo> record = new ProducerRecord<String, MyPojo>("usertopic", key,message);
        try {
            producer.send(record, new ProducerCallback());
            producer.flush();
        }
        finally {

        }

    }

我的主题上总共有10个分区,而我的生产者使用Round Robin类型的分区逻辑并平等地写入所有分区,为了在生产者端进行测试,有10个不同的线程分别写入1000条消息。

在消费者方面,有时我收到的消息多于发送的消息,我收到的消息类似于10867,其中我仅发送10000条消息。

我注意到我得到了这些重复,每个流都与下面的消息重新连接。

2019-07-14T00:11:06,043DEBUG[streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-6]c.j.m.s.UserKafkaStreamTopology:DataatStream
key:key-29value:{"userId":"message-468","data":null,"data1":null,"data3":null}
**2019-07-14T00:11:06,043INFO[streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-8]o.a.k.c.c.KafkaConsumer:[ConsumerclientId=streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-8-restore-consumer,groupId=]Unsubscribedalltopicsorpatternsandassignedpartitions
2019-07-14T00:11:06,043INFO[streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-8]o.a.k.s.p.i.StreamThread$RebalanceListener:stream-thread[streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-8]partitionrevocationtook16ms.
    suspendedactivetasks:[0_6]
    suspendedstandbytasks:[]
2019-07-14T00:11:06,044INFO[streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-8]o.a.k.c.c.i.AbstractCoordinator:[ConsumerclientId=streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-8-consumer,groupId=streams-user-process](Re-)joininggroup**
2019-07-14T00:11:06,043DEBUG[streams-user-process-ed85a88b-73c5-4416-9564-c15343fd53bd-StreamThread-6]c.j.m.s.UserKafkaStreamTopology:DataatStream
key:key-30value:{"userId":"message-569","data":null,"data1":null,"data3":null}

我需要帮助来理解为什么即使启用了True_once

也会收到更多记录

1 个答案:

答案 0 :(得分:2)

对于流处理仅执行一次即可保证对于每个接收到的记录,即使在失败的情况下,其处理结果也将被反映一次。

在Kafka上下文中,Exactly_once是一个适用于“ Kafka Streams”的概念,请记住,Kafka Streams旨在读取主题并生成主题。

在Kafka Streams世界中改写:“仅一次”表示只要且仅当状态被相应更新且输出记录成功生成一次时,任何输入记录的处理才被视为完成。

在您的特定情况下,日志key:key-30value:{"userId":"message-569","data":null,"data1":null,"data3":null}似乎是由拓扑的peek方法产生的。

如果您可以找到预期的事件数,则宁愿进入接收器主题

因为如果出于某种原因,您的Kafka Streams应用程序无法将消息发布到接收器主题,听起来正常,再次使用并处理传入的消息以产生出消息,然后保证“恰好一次”合同。这就是为什么同一条消息可以在日志中多次可见的原因。

您可以在https://www.confluent.io/blog/enabling-exactly-once-kafka-streams/

中找到更多详细信息。