Kafka基本操作、整合代码自定义分区器、提高吞吐量

基本命令

bin/kafka-topics.sh --bootstrap-server 192.168.6.101:9092 --list
# 创建名为test的主题
bin/kafka-topics.sh --bootstrap-server 192.168.6.101:9092 --create --partitions 1 --replication-factor 1 --topic first
#查看 first 主题的详情
bin/kafka-topics.sh --bootstrap-server 
192.168.6.101:9092 --alter --topic first --partitions 3
#修改
bin/kafka-topics.sh --bootstrap-server 192.168.6.101:9092 --topic first --alter --partitions 4
#删除 topic
bin/kafka-topics.sh --bootstrap-server 
192.168.6.101:9092 --delete --topic first

生产者命令行操作

像topic中发送数据
bin/kafka-console-producer.sh --bootstrap-server 192.168.6.101:9092 --topic first
在另一台虚拟机创建消费者取数据
bin/kafka-console-consumer.sh --bootstrap-server 192.168.6.101:9092 --topic first
取出所有数据
bin/kafka-console-consumer.sh --bootstrap-server 192.168.6.101:9092 --topic first --from-begining

整合代码

添加依赖

<dependencies>
 <dependency>
 <groupId>org.apache.kafka</groupId>
 <artifactId>kafka-clients</artifactId>
 <version>3.0.0</version>
 </dependency>
</dependencies>

创建客户端

package com.lzq.producer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;

public class CustomProducer {
    public static void main(String[] args) {
        //属性配置
        Properties properties = new Properties();
        //连接集群
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.6.101:9092");
        //指定k、v序列化类型
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
        //创建生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);
        //像first主题发送数据
        kafkaProducer.send(new ProducerRecord<>("first","hello"));
        //关闭资源
        kafkaProducer.close();
    }
}

回调发送数据

 //像first主题发送数据
        kafkaProducer.send(new ProducerRecord<>("first", "hello"), new Callback() {
            @Override
            public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                if (e==null){
                    System.out.println("发送成功,主题"+recordMetadata.topic()+"分区"+recordMetadata.partition());
                }
            }
        });

同步发送数据

当第一批数据处理完,才发送第二批数据

  kafkaProducer.send(new ProducerRecord<>("first", "hello"),new Callback() {
            @Override
            public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                if (e==null){
                    System.out.println("发送成功,主题"+recordMetadata.topic()+"分区"+recordMetadata.partition());
                }
            }
        }).get();

生产者分区

(1)便于合理使用存储资源,每个Partition在一个Broker上存储,可以把海量的数据按照分区切割成一 块一块数据存储在多台Broker上。合理控制分区的任务,可以实现负载均衡的效果。

(2)提高并行度,生产者可以以分区为单位发送数据;消费者可以以分区为单位进行消费数据。

分区规则

(1)指明partition的情况下,直 接将指明的值作为partition值

(2)没有指明partition值但有key的情况下,将key的hash值与topic的 partition数进行取余得到partition值

(3)既没有partition值又没有key值的情况下,Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直 使用该分区,待该分区的batch已满或者已完成,Kafka再随机一个分区进行使用(和上一次的分区不同)

指定分区

参数为topic,分区,key,value

kafkaProducer.send(new ProducerRecord<>("first", 1,"","hello")

自定义分区器

public class MyPartitioner implements Partitioner {
    //主题、序列化后的k、v k、v
    @Override
    public int partition(String s, Object o, byte[] bytes, Object o1, byte[] bytes1, Cluster cluster) {
        //获取数据
        String value = o1.toString();
        int partition;
        //如果包含lzq就发送到0号分区
        if (value.contains("lzq")){
            partition = 0;
        }else {
            partition = 1;
        }
        return 0;
    }

    @Override
    public void close() {

    }

    @Override
    public void configure(Map<String, ?> map) {

    }
}
public class CustomProducer {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //属性配置
        Properties properties = new Properties();
        //连接集群
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.6.101:9092");
        //指定k、v序列化类型
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
        //关联自定义分区
        properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"com.lzq.producer.MyPartitioner");
        //创建生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);
        //像first主题发送数据
        kafkaProducer.send(new ProducerRecord<>("first", 1,"","lzq"),new Callback() {
            @Override
            public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                if (e==null){
                    System.out.println("发送成功,主题"+recordMetadata.topic()+"分区"+recordMetadata.partition());
                }
            }
        }).get();
        //关闭资源
        kafkaProducer.close();
    }
}

提高吞吐量

// batch.size:批次大小,默认 16K
 properties.put(ProducerConfig.BATCH_SIZE_CONFIG, 16384);
 // linger.ms:等待时间,默认 0
 properties.put(ProducerConfig.LINGER_MS_CONFIG, 1);
 // RecordAccumulator:缓冲区大小,默认 32M:buffer.memory
 properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG, 33554432);
// compression.type:压缩,默认 none,可配置值 gzip、snappy、lz4 和 zstd
properties.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"snappy");

猜你喜欢

转载自blog.csdn.net/weixin_52210557/article/details/123540570