kafka新旧配置文件详解及API

创建topic:
    kafka-topics.sh --create --topic test --zookeeper s102:2181 --partitions 3 --replication-factor 2

列出topic:
    kafka-topics.sh --list --zookeeper s102:2181 
    
    
启动生产者:
    kafka-console-producer.sh --broker-list s102:9092 --topic test 
启动消费者:
    kafka-console-consumer.sh --zookeeper s102:2181 --topic test        //老API
    kafka-console-consumer.sh --bootstrap-server s102:9092 --topic t2    //新API



kafka数据在zk中的分布
====================================    
    /broker/topics/t1            partitions":{"1":[103,104],"0":[102,103]}
    /broker/topics/t1/partition/0/stat    "leader":102,"isr":[103,102]            //in-sync
    /broker/topics/t1/partition/1/stat    "leader":103,"isr":[104,103]

    分区    0    102
            103

        1    103
            104


    kafka真实数据,在linux中以 68byte头+数据


    s102:    tt-2    √    √
    s103:    tt-0    √    √
    s104:    tt-1    √    √

    分区:水平分散节点压力
        kafka的数据是以轮询方式发送到每个分区
        随意指定,依赖于硬件情况

    副本:提供备份
        最大不能超过broker数量


    leader:
        kafka产生数据时,先发送给leader
        非leader节点在之后同步leader数据    in-sync



消费者和消费者组:
==============================

    /consumers        //消费者组
                //默认创建控制台消费者,会创建一个新组


    创建消费者手动指定消费者组
        kafka-console-consumer.sh --topic t1 --zookeeper s102:2181 --group g2

    一个消费者组包括多个消费者,当数据产生时,消费者组中只有一个消费者能收到消息



从指定位置重复消费数据:
===================================
    原理:当消费者消费数据后,zk会记录一个偏移量,每消费一条数据,偏移量+1


    1、修改偏移量    /consumer/g2/offsets/
        将值设为自定义值
    
    2、在相同消费者组中启动另一个消费者


消费线程数:
====================================
    分区数 = 2    钱袋
    线程数 = 2    手


    一个消费者有多个消费线程,一个消费线程处理一个分区
    当分区 = 4 , 线程 = 2     消费者 = 1    此时消费者只能一个线程轮训监控两个分区        1X2X2    抢银行来回两次
                 消费者 = 2    此时两个消费者能够分别使用两个线程监控四个分区    2X2X1    抢银行两个人一次过
    
      分区 = 2 , 线程 = 2     消费者 = 1    此时消费者两个线程能够处理两个分区            一个人一次过
                 消费者 = 2    第二个消费者不监控任何分区                人多了,不带另一个玩
                 
    
producer配置文件:
================================

    metadata.broker.list    //连接kafka服务器的地址列表
                //s102:9092,s103:9092,s104:9092
            
    serializer.class    //指定message的消息格式 Encoder
                //默认DefaultEncoder ==> byte[] 
                //kafka.serializer.IntegerEncoder
                //kafka.serializer.LongEncoder
                //kafka.serializer.NullEncoder
                //kafka.serializer.StringEncoder

    key.serializer.class    //指定key的串行化格式


    producer.type        //生产者类型
                //包括sync和async
                //sync ===> 数据的同步传输    
                        类似于hbase中的put(put)
                        多用于严格有序,速度稍慢
                //async ==> 数据异步(批次)传输    
                        类似于hbase中的put(List<put>)
                        不严格有序,速度稍快

    request.required.acks    //控制生产者接收确认回执
                //0    代表不接收确认回执,最低延迟,持久性最差
                //1    只接收来自leader的确认回执,延迟稍低,持久性略好
                //-1    接收所有副本确认回执,延迟最差,持久性最好
                        
    partitioner.class    //kafka分区类,可以自定义
                
    compression.codec    //压缩编解码器
                //none, gzip, and snappy.
            

    batch.num.messages    //async模式设置批次大小
                //指定message个数
                //默认200

测试同步和异步生产:
    
    sync:    10000    //52,479ms
    async:    10000    //4,871ms


测试确认回执:
    async:    1    //3,319ms
    async: 0    //3,039ms
    async:  -1    //4,744ms


Consumer配置文件:
=========================================
        
    group.id        //对消费者组的唯一标识 id
        
    consumer.id        //对消费者的唯一标识

    zookeeper.connect    //指定zk连接串
                //s102:2181,s103:2181,s104:2181

    client.id        //客户端的唯一标识,类似于group.id

    zookeeper.session.timeout.ms    //zk会话超时

    zookeeper.connection.timeout.ms //zk连接超时

    zookeeper.sync.time.ms        //zk的follower和leader的同步时间

    auto.commit.enable        //启用自动提交consumer偏移量
                    //消费数据,偏移量会自动修改
                    //默认为true
                    //注意:偏移量在消费者组下

    auto.commit.interval.ms        //设置自动提交间隔

    auto.offset.reset        //重置偏移量
                    //自定义消费位置
                    //largest: 重置消费位置为最大偏移量
                    //smallest: 重置消费位置为最小偏移量
                    //anything else: 抛出异常

    consumer.timeout.ms        //消费者超时设置


偏移量:
    smallest:数据的最小偏移量    不一定是0    和zk无关,数据的起始
    largest: zk中数据偏移量

    
    日志保留时间:server.properties

    # 日志的删除时间,经过7天后自动删除
    log.retention.hours=168    
    # 超过此字节,数据会删除
    # log.retention.bytes=1073741824
    # 超过此字节,创建一个新数据段
    log.segment.bytes=1073741824


kafka中的分区:partition
=================================
    1、编写自定义分区:
        public class MyPartition implements Partitioner {
            public MyPartition(VerifiableProperties props) {
            }

            public int partition(Object key, int numPartitions) {

            Integer k = (Integer)key;

            return k % numPartitions;
            }
        }
    
    2、在生产者中指定分区
        public class MyProducer {
            public static void main(String[] args) throws Exception {
            long start = System.currentTimeMillis();
            Properties props = new Properties();
            props.put("metadata.broker.list", "s102:9092, s103:9092, s104:9092");
            props.put("serializer.class", "kafka.serializer.StringEncoder");
            //**********指定key序列化类型**********
            props.put("key.serializer.class", "kafka.serializer.IntegerEncoder");
            //**********指定分区类**********
            props.put("partitioner.class","kafka.MyPartition//完整类名");
            props.put("producer.type","async");
            props.put("request.required.acks", "0");
            ProducerConfig config = new ProducerConfig(props);
            Producer<Integer, String> producer = new Producer<Integer, String>(config);
            for (int i = 0; i < 10000; i++) {
                String msg = "tom" + i;
                //**********将key写入**********
                KeyedMessage<Integer, String> data = new KeyedMessage<Integer,String>("t3",i, msg);
                producer.send(data);
                Thread.sleep(2000);
            }
            producer.close();
            System.out.println(System.currentTimeMillis()- start);
            }
        }
    3、消费者观察数据与所在的分区对应关系




kafka新API:Producer配置文件
============================================
    kafka中发送方法:send()    是默认异步

    key.serializer    
    value.serializer
    acks            //0    没有回执
                //1    leader回执 
                //all    所有回执 
    retries            //发送数据失败重新发送的次数
    bootstrap.servers    //相当于老API中的metadata.broker.list
                //broker列表,kafka地址
    buffer.memory        //数据缓冲区内存大小,到达则会被发送,字节数long
    compression.type    //
    batch.size        //数据发送到同一分区,尝试将指定大小的数据量变为一个批次
                //小批次减少吞吐量    单位int
    client.id        //客户端id    string
    linger.ms        //记录在缓冲区中停留时间 long
    partitioner.class    //分区类


将kafka中异步发送改成同步
============================================
        Future future = producer.send(record, callback);

        Callback对象:send方法中的回调机制。在数据发送后的信息汇报
                  信息包括元数据(metadata),异常(exception)
              使用场景:当数据发送失败,能够从中获取元数据和异常状态
                      避免数据丢失,对数据再次处理

                new Callback() {
                public void onCompletion(RecordMetadata metadata, Exception exception) {
                    
                }
                } 

        Future对象:send方法的返回值,通过future.get()获取到元数据(metadata)
                通过调用future.get(),可以将异步变为同步
            原理:下一条记录必须要等前一个记录返回值调用之后才能够进行发送

    
        性能比较:
            async:    1000条数据:1239ms
        sync:    1000条数据:3360ms


kafka数据在分区中有序,跨分区无序,相当于Hadoop中的部分排序


producer新API的创建
============================================
    public class NewProducer {
        public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        props.put("bootstrap.servers", "s102:9092");
        props.put("acks", "0");
        props.put("linger.ms", 1);
        props.put("buffer.memory", 33554432);
        props.put("key.serializer", "org.apache.kafka.common.serialization.IntegerSerializer");
        props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        long start = System.currentTimeMillis();
        //初始化kafka生产者对象
        Producer<Integer, String> producer = new KafkaProducer<Integer, String>(props);
        for (int i = 0; i < 1000; i++) {
            //初始化kafka记录,包括topic,key,value
            ProducerRecord record = new ProducerRecord("t3",i,"tom"+ i);
            Future future = producer.send(record, new Callback() {
            public void onCompletion(RecordMetadata metadata, Exception exception) {
                System.out.println(metadata.toString());
                exception.printStackTrace();
            }
            });
            future.get();
        }
        producer.close();
        System.out.println(System.currentTimeMillis() - start);
        }
    }

Consumer新API的创建
============================================
    public class NewConsumer {
        public static void main(String[] args) {
        Properties props = new Properties();
        props.put("bootstrap.servers", "s102:9092");
        props.put("group.id", "g3");
        props.put("enable.auto.commit", "true");
        props.put("key.deserializer", "org.apache.kafka.common.serialization.IntegerDeserializer");
        props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        KafkaConsumer<Integer, String> consumer = new KafkaConsumer<Integer, String>(props);

        //新ConsumerAPI可以指定多主题订阅
        List<String> topics = new ArrayList<String>();
        topics.add("t3");
        topics.add("t2");
        consumer.subscribe(topics);

        while (true) {
            //通过poll方式获取数据,返回的是一个批次的数据
            ConsumerRecords<Integer, String> records = consumer.poll(1000);
            for (ConsumerRecord<Integer, String> record : records)
            System.out.println(
                "par: " + record.partition() +
                ",offset: "+ record.offset() +
                ", key: " + record.key() +
                ", value: " +record.value());
        }
        }
    }

Consumer新API的新特性:
============================================
    kafka-console-consumer.sh --bootstrap-server s102:9092 --topic t2    //启动控制台消费者


    1、指定分区消费,不能和 consumer.subscribe(topics)一起用
        List<TopicPartition> tps = new ArrayList<TopicPartition>();
        TopicPartition tp = new TopicPartition("t3",0);
        tps.add(tp);
        consumer.assign(tps);



    2、指定偏移量消费:off:3534    key:30    val:tom30
        前提:需要先指定分区分区进行消费
        //新ConsumerAPI可以指定分区进行消费
        List<TopicPartition> tps = new ArrayList<TopicPartition>();
        TopicPartition tp = new TopicPartition("t3",0);
        tps.add(tp);
        consumer.assign(tps);

        1、    //新ConsumerAPI可以指定偏移量消费
            //程度在于控制偏移量,类似于修改zk偏移量数据
            //consumer.commitSync(offsets)之后,所有消费者都从此处开始消费
            Map<TopicPartition, OffsetAndMetadata > offsets = new HashMap<TopicPartition, OffsetAndMetadata>();
            OffsetAndMetadata om = new OffsetAndMetadata(3534);
            offsets.put(tp,om);
            consumer.commitSync(offsets);
    
        
        2、    //将poll的指针移动到指定的偏移量,对consumer影响较小
            consumer.seek(tp,3500)

kafka新API:Consumer配置文件
============================================
    key.deserializer    //
    value.deserializer    //
    bootstrap.servers    //

    fetch.min.bytes        //consumer抓取请求数    int

    group.id        //自定义消费者组id

    heartbeat.interval.ms    //适用于consumer组,确保会话有效    int

    max.partition.fetch.bytes    //consumer抓取单个分区请求数    int

    session.timeout.ms    //超时视为会话失效

    auto.offset.reset    //重置偏移量
                //自定义消费位置
                //latest: 重置消费位置为最大偏移量
                //earliest: 重置消费位置为最小偏移量
                //none: 
                //other:抛出异常

    enable.auto.commit    //自动提交偏移量    boolean

    exclude.internal.topics    //决定内部topic是否暴露数据给消费者

    fetch.max.bytes        //一个批次获取的最大数据字节数 int

    isolation.level        //read_committed:只能读到提交的数据
                //read_uncommitted:能读到未提交的数据
                //producer的事务性
                props.put("transactional.id", "my-transactional-id");
                producer.initTransactions();
                producer.beginTransaction();
                producer.commitTransaction();
                producer.abortTransaction();


    max.poll.interval.ms    
    max.poll.records    //设置一次poll中最大记录数

猜你喜欢

转载自www.cnblogs.com/zyde/p/8946941.html