Kafka Consumer不使用事务语义(isolation.level = read_commited)

时间:2018-01-25 06:15:32

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

当Kafka Consumer在属性中具有事务语义时,它无法使用任何消息。但是当我删除该属性或将该属性更新为read_uncommited时,它消耗了消息。

以下是我的卡夫卡消费者物业: -

Properties props = new Properties();
    props.put("bootstrap.servers", "10.2.200.15:9092");
    String consumeGroup = "cg3";
    props.put("group.id", consumeGroup);
    // Below is a key setting to turn off the auto commit.
    props.put("enable.auto.commit", "false");
    props.put("heartbeat.interval.ms", "2000");
    props.put("session.timeout.ms", "6001");
    // Control maximum data on each poll, make sure this value is bigger than the
    // maximum // single message size
    props.put("max.partition.fetch.bytes", "140");
    props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    props.put("isolation.level","read_committed");

Kafka Producer在其属性中有一个Transactional id,在推送一些消息后,它将整个事务提交。以下是Kafka Producer Properties: -

log.info(“初始化属性”);         属性props = new Properties();

    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, System.getenv(KafkaConstants.KAFKA_URL));
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
            "org.apache.kafka.common.serialization.StringSerializer");
    props.put("linger.ms", 1000);
    props.put("acks", "all");
    // props.put("request.timeout.ms",30000);
    props.put("retries", 3);
    props.put("retry.backoff.ms", 1000);
    props.put("max.in.flight.requests.per.connection", 1); // if its greater than 1, it can change the order or records. Maximum no. of unacknowledge request a client can send.
    props.put("enable.idempotence", true);
    props.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG,"Transaction8");

以下代码段负责提交交易: -

public boolean send(ProducerRecordImpl record) {
    try {
        producer.beginTransaction();
        for (int i = 0; i < 10; i++) {


            Future<RecordMetadata> futureResult = producer
                    .send(new ProducerRecord<String, String>(record.getTopic(), record.getPayload()));
            /*
             * It will wait till the thread execution completes and return true.
             */
            //RecordMetadata ack = futureResult.get();
            //log.debug("RecordMetadta offset {} and partiton {} ", ack.offset(), ack.partition());
        }
        producer.commitTransaction();
        log.info("Commited");


        return true;

我无法理解生产者方是否发生了正确的提交,这导致Kafka Consumer无法使用Kafka Consumer方面的事务语义或问题来阅读它。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

您需要先调用producer.initTransactions()。否则,您的制作人不会发布交易消息。

来自https://kafka.apache.org/0110/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html#initTransactions()

  

在transactional.id之前需要在任何其他方法之前调用   在配置中设置。此方法执行以下操作:1。   确保之前的实例发起的任何交易   生成器具有相同的transactional.id已完成。如果是以前的   实例在进行中的事务中失败了,它将是   中止。如果最后一笔交易已经开始完成,但尚未完成   完成后,这种方法等待完成。 2.获取内部   生产者ID和纪元,用于所有未来的交易消息   由制片人发行。

答案 1 :(得分:0)

在Kafka上测试事务时我遇到了同样的问题。问题是操作系统。我使用Windows 10来运行Kafka代理,当我将代理配置为&#34; read_committed&#34;时,消费者无法看到任何已提交的事务,一旦我将代理移动到Linux,交易(和消费者) )开始工作了。 顺便说一句,Kafka没有向我显示日志中的任何错误。 希望它有所帮助。