kafka第二天 acks,reties,幂等性

幂等写:针对的是producer,并且只能 保证同一个分区的消息不重复
acks:kafka的客户端(Producer),发送一条数据,会等待broker返回成功的响应;
有三种配置:ProducerConfig.ACKS_CONFIG=“?”
0:不需要响应,producer发送就完了,不管broker是否消费成功;
1:只需要broker的leader返回响应 就行,不需要followers的同步确认,如果leader返回确认后立即挂了,followers没有同步,数据会丢失
all/-1:all或者-1:表示需要leader和 followers的确认 才行,保证了数据至少有一个follower副本,数据安全性高;

reties:重试次数,当没有收到server响应的时候product重试的次数
参数:ProducerConfig.RETRIES_CONFIG=int
Producer

public static void main(String[] args) {

        Properties properties = new Properties();
        // 获取节点
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"node05kafka:9092,node06kafka:9092,node07kafka:9092");
        //序列化
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class);
        // 设置应答机制,0,不需要应答,>0,只需要leader应答,all/-1:需要leader和副本都应答,数据安全性高
        properties.put(ProducerConfig.ACKS_CONFIG,"-1");
        // 重试次数
        properties.put(ProducerConfig.RETRIES_CONFIG,3);
        // 每个连接的最大并发数,1:只允许一个,保证数据的强顺序性,如果有数据没有应答,product阻塞等待响应
        properties.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION,1);
        //连接超时时间 ms 这里为了方便模拟没有应答场景
        properties.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG,1);
        // 创建product
        KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);

        
        // 封装消息队列
//        for (int i = 0; i < 30; i++) {
            //封装消息
            ProducerRecord<String, String> record = new ProducerRecord<String, String>("topic02","ack","ack  test");
            producer.send(record);
//        }
        producer.close();
    }

consumer

public static void main(String[] args) {
        //获取连接
        Properties properties = new Properties();
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"node05kafka:9092,node06kafka:9092,node07kafka:9092");
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);
        properties.put(ConsumerConfig.GROUP_ID_CONFIG,"g2");
        //创建consumer
        KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
        // 订阅相关的topic
        consumer.subscribe(Pattern.compile("^topic.*"));
        //遍历消息队列
        while (true){
            // 多久拉取一次消息aA
            ConsumerRecords<String, String> records = consumer.poll(Duration.ofSeconds(1));
            if(!records.isEmpty()){
                //获取消息的迭代器
                Iterator<ConsumerRecord<String, String>> recordIterator = records.iterator();
                while (recordIterator.hasNext()){
                    // 获取一条消息
                    ConsumerRecord<String, String> record = recordIterator.next();
                    String key = record.key();
                    String value = record.value();
                    long offset = record.offset();
                    int partition = record.partition();
                    String topic = record.topic();
                    long timestamp = record.timestamp();
                    System.out.println(key+"\t"+value+"\t"+offset+"\t"+partition+"\t"+topic+"\t"+timestamp);

                }
            }
        }

    }

结果:

consumer的控制台 看到,消息重复了
ack	ack  test	0	2	topic02	1603247463946
ack	ack  test	1	2	topic02	1603247463946
ack	ack  test	2	2	topic02	1603247463946
ack	ack  test	3	2	topic02	1603247463946

要解决消息的重复消费要使用幂等性解决
幂等:多次发送的相同的数据,和一次发送该数据,结果相同;
ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG=true;默认false;
当设置为“ true”时,生产者将确保每个消息的确切副本被写入流中。
* 如果为“ false”,则由于代理故障等导致的生产者重试,可能会将重试消息的副本写入流中。
* 请注意,启用幂等性要求
* MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION 小于或等于5,
* RETRIES_CONFIG 大于0且ACKS_CONFIG 必须为’all’。
* 如果用户未明确设置这些值,则将选择合适的值。
* 如果设置了不兼容的值,抛出ConfigException;
原理:
HTTP/1.1中对幂等性的定义是:一次和多次请求某一个 资源对于 资源本 身应该具有同样的结果(网络超 时等 问题除外)。也就是说,其任意多次 执行对资源本身所产生的影响均与一次执行的 影响相同。Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.Kafka在0.11.0.0版本支持增加 了对幂等的支持。幂等是针对生产者角度的特性。幂等可以保证上生产者发送的消息,不会丢失,而且不会重复。实现幂等的关键点就是服务端可以区分请求是 否重复,过滤掉 重复的请求。要区分请求是否重复的有两点:唯一标识:要想区分 请求是 否重复,请求中 就得有唯一标识。 例如支 付请求中,订单号就是唯一标识记录下已处理过的请求标识:光有唯一标识还不够,还需要记录 下那 些请求是已经处理过的,这样当收到新 的请求时,用新请求中的 标识和处理记录进行比较,如果处理记录中有相同的标识,说明是重复记录,拒绝掉。
幂等性幂等又 称为exactly once。要 停止多次处理消息,必须仅 将其持久化到Kafka Topic中仅仅一次。在初始化期间,kafka会给生产者生成一个唯一的ID称为Producer ID或PID。PID和序列 号与消息 捆绑在一 起,然后发送给Broker。由于序列号从零开始并且单 调递增,因此,仅当消息的序列号比该PID / TopicPartition对中 最后提 交的消息正好大1时,Broker才会接受该消息。如果不是这种情况,则Broker认定是生产者重新发送该消息。

public static void main(String[] args) {

        Properties properties = new Properties();
        // 获取节点
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"node05kafka:9092,node06kafka:9092,node07kafka:9092");
        //序列化
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class);
        // 设置应答机制,0,不需要应答,>0,只需要leader应答,all/-1:需要leader和副本都应答,数据安全性高
        properties.put(ProducerConfig.ACKS_CONFIG,"-1");
        // 重试次数
        properties.put(ProducerConfig.RETRIES_CONFIG,3);
        // 每个连接的最大并发数,1:只允许一个,保证数据的强顺序性,如果有数据没有应答,product阻塞等待响应
        properties.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION,1);
        //连接超时时间
        properties.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG,1);
        // 幂等 默认关闭
        /**
         * 当设置为“ true”时,生产者将确保每个消息的确切副本被写入流中。
         * 如果为“ false”,则由于代理故障等导致的生产者重试,可能会将重试消息的副本写入流中。
         * 请注意,启用幂等性要求
         * MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION 小于或等于5,
         * RETRIES_CONFIG 大于0且ACKS_CONFIG 必须为'all'。
         * 如果用户未明确设置这些值,则将选择合适的值。
         * 如果设置了不兼容的值,抛出ConfigException;
         */
        properties.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG,true);

        // 创建product
        KafkaProducer<String, String> producer = new KafkaProducer<String, String>(properties);


        // 封装消息队列
//        for (int i = 0; i < 30; i++) {
            //封装消息
            ProducerRecord<String, String> record = new ProducerRecord<String, String>("topic02","ack","ack  test");
            producer.send(record);
//        }
        producer.close();
    }
WARN 2020-10-21 11:01:06 org.apache.kafka.clients.producer.internals.Sender - [Producer clientId=producer-1] Got error produce response with correlation id 49 on topic-partition topic02-2, retrying (2 attempts left). Error: NETWORK_EXCEPTION
WARN 2020-10-21 11:01:06 org.apache.kafka.clients.producer.internals.Sender - [Producer clientId=producer-1] Received invalid metadata error in produce request on partition topic02-2 due to org.apache.kafka.common.errors.NetworkException: The server disconnected before a response was received.. Going to request metadata update now
WARN 2020-10-21 11:01:06 org.apache.kafka.clients.producer.internals.Sender - [Producer clientId=producer-1] Got error produce response with correlation id 54 on topic-partition topic02-2, retrying (1 attempts left). Error: NETWORK_EXCEPTION
WARN 2020-10-21 11:01:06 org.apache.kafka.clients.producer.internals.Sender - [Producer clientId=producer-1] Received invalid metadata error in produce request on partition topic02-2 due to org.apache.kafka.common.errors.NetworkException: The server disconnected before a response was received.. Going to request metadata update now
WARN 2020-10-21 11:01:07 org.apache.kafka.clients.producer.internals.Sender - [Producer clientId=producer-1] Got error produce response with correlation id 71 on topic-partition topic02-2, retrying (0 attempts left). Error: NETWORK_EXCEPTION
WARN 2020-10-21 11:01:07 org.apache.kafka.clients.producer.internals.Sender - [Producer clientId=producer-1] Received invalid metadata error in produce request on partition topic02-2 due to org.apache.kafka.common.errors.NetworkException: The server disconnected before a response was received.. Going to request metadata update now

consumer的控制台日志 ;使用上面的consumer例子;

INFO 2020-10-21 11:00:22 org.apache.kafka.clients.consumer.internals.AbstractCoordinator - [Consumer clientId=consumer-1, groupId=g2] Successfully joined group with generation 2
INFO 2020-10-21 11:00:22 org.apache.kafka.clients.consumer.internals.ConsumerCoordinator - [Consumer clientId=consumer-1, groupId=g2] Setting newly assigned partitions: topic01-2, topic01-1, topic02-2, topic01-0, topic02-1, topic02-0
ack	ack  test	4	2	topic02	1603249261354

正常的响应应答
在这里插入图片描述
幂等写

在这里插入图片描述
HTTP/1.1中对幂等性的定义是:一次和多次请求某一个 资源对于 资源本 身应该具有同样的结果(网络超 时等 问题除外)。也就是说,其任意多次 执行对资源本身所产生的影响均与一次执行的 影响相同。Methods can also have the property of “idempotence” in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.Kafka在0.11.0.0版本支持增加 了对幂等的支持。幂等是针对生产者角度的特性。幂等可以保证上生产者发送的消息,不会丢失,而且不会重复。实现幂等的关键点就是服务端可以区分请求是 否重复,过滤掉 重复的请求。要区分请求是否重复的有两点:唯一标识:要想区分 请求是 否重复,请求中 就得有唯一标识。 例如支 付请求中,订单号就是唯一标识记录下已处理过的请求标识:光有唯一标识还不够,还需要记录 下那 些请求是已经处理过的,这样当收到新 的请求时,用新请求中的 标识和处理记录进行比较,如果处理记录中有相同的标识,说明是重复记录,拒绝掉。
幂等性幂等又 称为exactly once。要 停止多次处理消息,必须仅 将其持久化到Kafka Topic中仅仅一次。在初始化期间,kafka会给生产者生成一个唯一的ID称为Producer ID或PID。PID和序列 号与消息 捆绑在一 起,然后发送给Broker。由于序列号从零开始并且单 调递增,因此,仅当消息的序列号比该PID / TopicPartition对中 最后提 交的消息正好大1时,Broker才会接受该消息。如果不是这种情况,则Broker认定是生产者重新发送该消息。

坚持补充需要的知识

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值