初识kafka 之 分区策略

kafka 分区策略

1.指明partition的情况下,直接将指明的值作为partition值;
   例如partition=0,所有数据写入分区0
2.没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值;
   例如:key1的hash值=5, key2的hash值=6 ,topic的partition数=2,那么key1对应的value1写入1号分区,key2对应的value2写入0号分区。
   例如:要把一张表的数据入到同一个分区,可以指定key的值为该表名

3.既没有partition值又没有key值的情况下,Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,待该分区的batch已满或者已完成,Kafka再随机一个分区进行使用(和上一次的分区不同)。
   例如:第一次随机选择0号分区,等0号分区当前批次满了(默认16k)或者linger.ms设置的时间到, Kafka再随机一个分区进行使用(如果还是0会继续随机)。

代码实现

package com.lzh.kafka;

import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;
import java.util.concurrent.ExecutionException;

/* kafka 分区策略
1.指明partition的情况下,直接将指明的值作为partition值;
    例如partition=0,所有数据写入分区0
2.没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值;
    例如:key1的hash值=5, key2的hash值=6 ,topic的partition数=2,那么key1对应的value1写入1号分区,key2对应的value2写入0号分区。
    例如:要把一张表的数据入到同一个分区,可以指定key的值为该表名

3.既没有partition值又没有key值的情况下,Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,
  待该分区的batch已满或者已完成,Kafka再随机一个分区进行使用(和上一次的分区不同)。
    例如:第一次随机选择0号分区,等0号分区当前批次满了(默认16k)或者linger.ms设置的时间到, Kafka再随机一个分区进行使用(如果还是0会继续随机)。
*/

public class CustomProducerPartition {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1.配置
        Properties properties = new Properties();

        // 连接集群
        // 给kafka对象添加配置信息 bootstrap.servers
        // 生产者连接集群所需的 broker 地址清单
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"bigdata01:9092,bigdata02:9092");


        // 指定发送消息的key和value的序列化类型。一定要写全类名。
        // key,value序列化 key.serializer,value.serializer

        // key序列化
        // 全类名与下等价: properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        // value序列化
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());

        // 2.创建 kafka 生产者对象
        KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(properties);

        // 3.发送数据
        // 调用 send 方法,发送消息

        // 指定分区 partition
        for (int i = 1; i < 5; i++) {
            kafkaProducer.send(new ProducerRecord<String, String>("Mytopic",3,"","" + i), new Callback() { // 有回调函数
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e == null) {
                        System.out.println("主题"+ recordMetadata.topic() +"已异步发送消息到指定分区"+ recordMetadata.partition());
                    }
                }
            });
        }

        // 指定 key,把同一张的数据入到同一个分区 key就是表名
        for (int i = 1; i < 10; i++) {
            final int n;
            n=i;
            kafkaProducer.send(new ProducerRecord<String, String>("Mytopic","tab_name","记录"+i), new Callback() { // 有回调函数
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e == null) {
                        System.out.println("表tab_name的第"+ n +"条记录已发送到主题" + recordMetadata.topic() + "的指定分区" + recordMetadata.partition());
                    }
                }
            });
        }

        // 4.关闭资源
        kafkaProducer.close();

    }
}

结果

 

 

posted on 2022-04-14 15:23  Simple-Sir  阅读(760)  评论(0编辑  收藏  举报

导航