简体   繁体   English

NotEnoughReplicasException 与 min.insync.replicas 的意外行为

[英]Unexpected behaviour of NotEnoughReplicasException with min.insync.replicas

This is a continuation of my previous question这是我上一个问题的延续

I was experimenting kafka's min.insync.replicas and here's the summary:我正在试验 kafka 的min.insync.replicas ,这是摘要:

  1. Setup 3 brokers in local, created a topic insync with min.insync.replicas=2 .在本地设置3个经纪人,创建了一个主题insyncmin.insync.replicas=2
  2. Messages were produced by kafka-console-producer with acks=all and read by kafka-console-consumer消息由kafka-console-produceracks=all并由kafka-console-consumer读取
  3. Bought down 2 brokers leaving just 1 insync.replicas and was expecting an exception in producer as mentioned here and here购买了 2 个代理,只留下 1 个insync.replicas ,并期望生产者出现异常,如此此处所述

But it never happened and producer was producing messages and consumer was reading them from console without any errors.(more details in previous question )但它从未发生过,生产者正在生产消息,消费者正在从控制台读取它们而没有任何错误。(更多细节在上一个问题中

Then, Instead of producing messages from console-producer , I wrote a java producer with same configurations as console producer and finally got the following exception.然后,我没有从console-producer生成消息,而是编写了一个与控制台生产者配置相同的java生产者,最终得到了以下异常。

ERROR [Replica Manager on Broker 0]: Error processing append operation on partition insync-0 (kafka.server.ReplicaManager) org.apache.kafka.common.errors.NotEnoughReplicasException: Number of insync replicas for partition [insync,0] is [ 1 ], below required minimum [ 2 ]错误 [代理 0 上的副本管理器]:在分区 insync-0 (kafka.server.ReplicaManager) org.apache.kafka.common.errors.NotEnoughReplicasException 上处理附加操作时出错:分区 [insync,0] 的异步副本数为 [ 1 ],低于最低要求 [ 2 ]

Although I expected it from the producer(java code), it showed up in the kafka broker .虽然我期望它来自生产者(java 代码),但它出现在kafka broker 中

Console producer command控制台生产者命令

 ./kafka-console-producer.sh --broker-list localhost:9092 --topic insync --producer.config ../config/producer.properties

kafka-console-producer properties: kafka-console-producer 属性:

bootstrap.servers=localhost:9092,localhost:9093,localhost:9094
compression.type=none
batch.size=20
acks=all

Java producer code: Java生产者代码:

public static void main(String[] args) {
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(producerConfigs());

        try {

            int count = 0;
            while (true) {
                ProducerRecord<String, String> record = new ProducerRecord<String, String>("insync",
                        "test message: " + count);
                kafkaProducer.send(record);

                Thread.sleep(3000);
                count++;
            }
        } catch (Exception e) {

            e.printStackTrace();
        } finally {
            kafkaProducer.close();
        }
    }

    private static Properties producerConfigs() {
        Properties properties = new Properties();

        properties.put("bootstrap.servers", "localhost:9092,localhost:9093,localhost:9094");
        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        properties.put("acks", "all");

        return properties;
    }

This brings me more questions.这给我带来了更多的问题。

  1. Why does it happen while running java producer and not in console-producer.?为什么会在运行 java 生产者而不是在控制台生产者中发生。?
  2. Why does the exception occur in broker and not in producer(java code)?为什么异常发生在经纪人而不是生产者(java代码)中? the documentation for min.insync.replicas says min.insync.replicas文档

    If this minimum cannot be met, then the producer will raise an exception (either NotEnoughReplicas or NotEnoughReplicasAfterAppend)如果无法满足此最小值,则生产者将引发异常(NotEnoughReplicas 或 NotEnoughReplicasAfterAppend)

How does kafka guarantee reliability in this case?这种情况下kafka是如何保证可靠性的?

When producing with acks=all to a topic that has less in-sync replicas than min.insync.replicas , the producer should get NotEnoughReplicas .当使用acks=all生产同步副本少于min.insync.replicas ,生产者应该获得NotEnoughReplicas

The reason why you are not seeing this behavior is because you have issues with both the console producer command and the Java code.您没有看到此行为的原因是控制台生产者命令和 Java 代码都存在问题。

1. Console Producer 1. 控制台生产者

To enable acks=all in the kafka-console-producer.sh , you need to specify the --request-required-acks flag:要在kafka-console-producer.sh启用acks=all ,您需要指定--request-required-acks标志:

./kafka-console-producer.sh --broker-list localhost:9092 \
    --topic insync --request-required-acks all

This is because the --request-required-acks flag takes precedence over the values specified via --producer.config and it defaults to 1 .这是因为--request-required-acks标志优先于通过--producer.config指定的值,并且默认为1

2. Java code 2.Java代码

The code you have pasted should be failing to send any messages but with the current logic you should only get WARN log messages like:您粘贴的代码应该无法发送任何消息,但按照当前的逻辑,您应该只会收到WARN日志消息,例如:

Got error produce response with correlation id 15 on topic-partition , retrying ...在 topic-partition 上得到了相关 ID 为 15 的错误产生响应,正在重试...

To get notified in your code, you need to check the result of send() , via either checking the Future it returns or passing a Callback as the 2nd argument.要在您的代码中获得通知,您需要检查send()的结果,方法是检查它返回的Future或将Callback作为第二个参数传递。 Not also that NotEnoughReplicasException is a retriable exception so with the latest client, by default, it will retry forever instead of notifying the calling code.也不是NotEnoughReplicasException是可重试的异常,因此对于最新的客户端,默认情况下,它将永远重试而不是通知调用代码。

For example:例如:

Properties configs = new Properties();
configs.put("bootstrap.servers", "localhost:9092");
configs.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
configs.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
configs.put("retries", "5");
configs.put("acks", "all");

try (KafkaProducer<String, String> producer = new KafkaProducer<>(configs)) {
    ProducerRecord<String, String> record = new ProducerRecord<>(TOPIC, "value");
    producer.send(record, (RecordMetadata metadata, Exception exc) -> {
        if (exc != null) {
            System.err.println(exc);
        }
    });
}

When the topic is below minimun ISR, the producer will retry 5 times before failing the record.当主题低于最小 ISR 时,生产者将在记录失败之前重试 5 次。 It will then call the lambda with the exception, so you'll get:然后它会用异常调用 lambda,所以你会得到:

org.apache.kafka.common.errors.NotEnoughReplicasException: Messages are rejected since there are fewer in-sync replicas than required. org.apache.kafka.common.errors.NotEnoughReplicasException:消息被拒绝,因为同步副本少于所需。


So to conclude, min.insync.replicas is handled correctly but you need to be careful to pass the correct arguments to the tool, handle exceptions correctly in Java logic.所以总而言之, min.insync.replicas被正确处理,但您需要小心地将正确的参数传递给工具,在 Java 逻辑中正确处理异常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM