Introdução ao Kafka, envio manual de compensações, envio síncrono, envio assíncrono, especificação do consumo de deslocamento (23)

Envie o deslocamento manualmente

insira a descrição da imagem aqui
Embora o deslocamento seja muito transversal, é difícil para os desenvolvedores compreender a realidade do envio do deslocamento porque ele é enviado com base no tempo. Portanto, Kafka também fornece uma API para enviar compensações manualmente.
Existem dois métodos para enviar compensações manualmente: commitSync (envio síncrono) e commitAsync (envio assíncrono). O mesmo ponto entre os dois é que o maior deslocamento de um lote de dados enviado desta vez será enviado: a diferença é que o envio síncrono bloqueia o thread atual até que o envio seja bem-sucedido e falhará automaticamente e tentará novamente (causado por incontrolável Factors), também haverá uma falha de envio) e o envio assíncrono não tem mecanismo de repetição, portanto, o envio pode falhar.
commitSync (envio síncrono): você deve aguardar o envio do deslocamento antes de consumir o próximo lote de dados.
commitAsync (submissão assíncrona): Após enviar e enviar a solicitação de deslocamento, o próximo lote de dados será consumido

confirmação síncrona

是否自动提交offset properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,false);
同步提交offset kafkaConsumer.commitSync();

Como o envio síncrono de compensação tem um mecanismo de repetição de falha, é mais confiável, mas devido à espera unânime pelo resultado do envio, a eficiência do envio é relativamente baixa. Veja a seguir um exemplo de envio de compensação de forma síncrona

package com.longer.handsync;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Properties;

public class CustomConsumerByHandSync {
    
    
    public static void main(String[] args) {
    
    
        //创建消费者的配置对象
        Properties properties=new Properties();
        //2、给消费者配置对象添加参数
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop100:9092");
        //配置序列化
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
        //配置消费者组(组名任意起名)必须
        properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");
        //修改分区策略
        properties.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,"org.apache.kafka.clients.consumer.StickyAssignor");
//        properties.put(ConsumerConfig.EXCLUDE_INTERNAL_TOPICS_CONFIG,"false");
        //是否自动提交offset
        properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,false);
        //创建消费者对象
        KafkaConsumer<String,String> kafkaConsumer=new KafkaConsumer<String, String>(properties);
        //注册要消费的主题
        ArrayList<String> topics=new ArrayList<>();
        topics.add("two");
        kafkaConsumer.subscribe(topics);
        while (true){
    
    
            //设置1s中消费一批数据
            ConsumerRecords<String,String> consumerRecords=kafkaConsumer.poll(Duration.ofSeconds(1));
            //打印消费到的数据
            for(ConsumerRecord<String,String> record:consumerRecords){
    
    
                System.out.println(record);
            }
            //同步提交offset
             kafkaConsumer.commitSync();
        }
    }
}

confirmação assíncrona

Embora o envio síncrono de deslocamento seja mais confiável, ele bloqueará o thread atual até que o envio seja bem-sucedido. Portanto, a taxa de transferência será bastante afetada; portanto, em mais casos, o método de deslocamento assíncrono será escolhido
kafkaConsumer.commitAsync();

package com.longer.handasync;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Properties;

/**
 * 同步提交
 */
public class CustomConsumerByHandAsync {
    
    
    public static void main(String[] args) {
    
    
        //创建消费者的配置对象
        Properties properties=new Properties();
        //2、给消费者配置对象添加参数
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop100:9092");
        //配置序列化
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
        //配置消费者组(组名任意起名)必须
        properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");
        //修改分区策略
        properties.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,"org.apache.kafka.clients.consumer.StickyAssignor");
//        properties.put(ConsumerConfig.EXCLUDE_INTERNAL_TOPICS_CONFIG,"false");
        //是否自动提交offset
        properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,false);
        //创建消费者对象
        KafkaConsumer<String,String> kafkaConsumer=new KafkaConsumer<String, String>(properties);
        //注册要消费的主题
        ArrayList<String> topics=new ArrayList<>();
        topics.add("two");
        kafkaConsumer.subscribe(topics);
        while (true){
    
    
            //设置1s中消费一批数据
            ConsumerRecords<String,String> consumerRecords=kafkaConsumer.poll(Duration.ofSeconds(1));
            //打印消费到的数据
            for(ConsumerRecord<String,String> record:consumerRecords){
    
    
                System.out.println(record);
            }
            //同步提交offset
            kafkaConsumer.commitAsync();
        }
    }
}

Especifique o consumo de compensação

auto.offset.reset = mais cedo | mais recente | nenhum O padrão é o mais recente
quando não há deslocamento inicial no Kafka (o grupo de consumidores consome pela primeira vez) ou o deslocamento atual não existe mais no servidor (por exemplo, os dados foram excluído), o que fazer?
1) mais cedo: redefinir automaticamente o deslocamento para o deslocamento mais antigo, --from-beginning
2) mais recente (padrão): redefinir automaticamente o deslocamento para o deslocamento mais recente
3) se nenhum grupo de consumidores for encontrado, uma exceção será lançada para o consumidor.
insira a descrição da imagem aqui
Código principal

		Set<TopicPartition> assigment=new HashSet<>();

        while (assigment.size()==0){
    
    
            kafkaConsumer.poll(Duration.ofSeconds(1));
            //获取消费者分区分配信息(有了分区分配信息才能开始消费)
            assigment= kafkaConsumer.assignment();
        }
        //遍历所有分区,并指定从100得位置开始消费
        for (TopicPartition tp : assigment) {
    
    
            kafkaConsumer.seek(tp,100);
        }
package com.longer.seek;

import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.serialization.StringDeserializer;

import java.time.Duration;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

public class CustomConsumerSeek {
    
    
    public static void main(String[] args) {
    
    
        //创建消费者的配置对象
        Properties properties=new Properties();
        //2、给消费者配置对象添加参数
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop100:9092");
        //配置序列化
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
        //配置消费者组(组名任意起名)必须
        properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");
        //修改分区策略
        properties.put(ConsumerConfig.PARTITION_ASSIGNMENT_STRATEGY_CONFIG,"org.apache.kafka.clients.consumer.StickyAssignor");
//        properties.put(ConsumerConfig.EXCLUDE_INTERNAL_TOPICS_CONFIG,"false");

        //创建消费者对象
        KafkaConsumer<String,String> kafkaConsumer=new KafkaConsumer<String, String>(properties);
        //注册要消费的主题
        ArrayList<String> topics=new ArrayList<>();
        topics.add("two");
        kafkaConsumer.subscribe(topics);

        Set<TopicPartition> assigment=new HashSet<>();

        while (assigment.size()==0){
    
    
            kafkaConsumer.poll(Duration.ofSeconds(1));
            //获取消费者分区分配信息(有了分区分配信息才能开始消费)
            assigment= kafkaConsumer.assignment();
        }
        //遍历所有分区,并指定从100得位置开始消费
        for (TopicPartition tp : assigment) {
    
    
            kafkaConsumer.seek(tp,100);
        }


        while (true){
    
    
            //设置1s中消费一批数据
            ConsumerRecords<String,String> consumerRecords=kafkaConsumer.poll(Duration.ofSeconds(1));
            //打印消费到的数据
            for(ConsumerRecord<String,String> record:consumerRecords){
    
    
                System.out.println(record);
            }
        }
    }
}

Acho que você gosta

Origin blog.csdn.net/weixin_43205308/article/details/131637794
Recomendado
Clasificación