kafka基础

Kafka

一种高吞吐量的分布式发布-订阅消息系统,专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计

  • Kafka架构

    Topic:维护一个主题中的消息,可视为消息分类

     主题是已发布消息的类别名称
     发布和订阅数据必须指定主题
     主题副本数量不大于Brokers个数
    

    Producer:向Kafka主题发布(生产)消息
    Consumer:订阅(消费)主题并处理消息
    Broker:Kafka集群中的服务器
    在这里插入图片描述

  • Partition

    1、一个主题包含多个分区,默认按Key Hash分区
    2、每个Partition对应一个文件夹<topic_name>-<partition_id>
    3、每个Partition被视为一个有序的日志文件(LogSegment)
    4、Replication策略是基于Partition,而不是Topic
    5、每个Partition都有一个Leader,0或多个Followers

  • Consumer

    1、offset的管理是基于消费组(group.id)的级别
    2、每个Partition只能由同一消费组内的一个Consumer来消费
    3、每个Consumer可以消费多个分区
    4、消费过的数据仍会保留在Kafka中
    5、消费者不能超过分区数量

  • Kafka数据流

    副本同步(ISR)、容灾(Leader Partition)、高并发(读写性能、Consumer Group)、负载均衡

在这里插入图片描述

  • Kafka 是如何实现高吞吐的?

      顺序读写:是不断追加到文件中的;
      零拷贝:只用将磁盘文件的数据复制到页面缓存中一次,然后将数据从页面缓存直接发送到网络中;
      分区: Kafka 的队列 topic 被分为了多个区 partition,每个partition又分为多个段segment, 每次文件操作都是对一个小文件的操作, 也增加了并行处理能力
      批量发送: 允许进行批量发送消息,先将消息缓存在内存中,然后一次请求批量发送出去, 大大减少服务端的 I/O 次数
      数据压缩: Producer 可以通过 GZIP 或 Snappy 格式对消息集合进行压缩压缩的好处就是减少传输的数据量,减轻对网络传输的压力
      Consumer 的负载均衡: 当一个 group 中,有 consumer 加入或者离开时,会触发 partitions 均衡.均衡的最终目的,是提升topic 的并发消费能力
    
  • Kafka Producer API

<dependency>
       <groupId>org.apache.kafka</groupId>
       <artifactId>kafka-clients</artifactId>
       <version>2.3.0</version>
 </dependency>
 
  	val pro = new Properties()
    //设置kafka集群,kafka集群的broker-list
    pro.put("bootstrap.servers","single:9092")
    //0不需要leader partition确认接收成功
    //1需要等待
    //-1(all)需要leader和isr列表的follower都确认成功
    pro.put("acks","all")
    //Key和value序列化
    pro.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    pro.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
    //创建kafka生产者
    val producer = new KafkaProducer[String,String](pro)
    for(i<-1 to 100) {
      producer.send(new ProducerRecord[String,String("topic",Integer.toString(i), "dd:"+i))
    }
    producer.close()
  • Kafka Consumer API

	val pro = new Properties()
    //设置kafka集群,kafka集群的broker-list
    pro.put("bootstrap.servers", "single:9092")
    //设置消费者组id
    pro.put("group.id", "testGroup1");
    pro.put("enable.auto.commit", "true"); //默认值true
    //每隔1000ms提交一次
    pro.put("auto.commit.interval.ms", "1000"); //默认值5000

    //Key和value反序列化
    pro.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    pro.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
    val consumer = new KafkaConsumer[String, String](pro)
    val topic=new util.ArrayList[String]()
    topic.add("test")
    consumer.subscribe(topic)
    //设置超时时间,单位为毫秒,返回一些条数据
    while (true) {
      val records: ConsumerRecords[String, String] = consumer.poll(1000)
      val it = records.iterator()
      while (it.hasNext) {
        val next = it.next()
        println(s"partition=${next.partition()},offset=${next.offset()},key=${next.key()},value=${next.value()}")
      }
    }
  • 手动提交Offset

 	val props = new Properties()
    // 配置Kafka集群的ip和端口号
    props.put("bootstrap.servers", "single:9092")
    // 设置消费者组的id, 如果有多个相同id的消费者程序, 那么他们将在一个组当中
    props.put("group.id", "testGroup1")
    // 关闭自动提交[默认就是开启]
    props.put("enable.auto.commit", "false")
    // key和value的反序列化
    props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    // 创建一个Consumer客户端
    val consumer = new KafkaConsumer[String, String](props)
    // consumer消费
    val topics = new util.ArrayList[String]()
    topics.add("test")
    // 订阅topic
    consumer.subscribe(topics)

    val parts = new util.ArrayList[TopicPartition]()
    parts.add(new TopicPartition("test",0))
    consumer.assign(parts)
    // 创建一个集合, 用来存放消息的个数
    val buffer = new util.ArrayList[ConsumerRecord[String, String]]()
    // 为了能够一直从Kafka中消费数据, 使用 while true 死循环
    while (true) {
      // 设置超时时间, 单位是毫秒, 返回一些条数据
      val records: ConsumerRecords[String, String] = consumer.poll(1000)
      // 对这些数据进行遍历输出
      val iter: util.Iterator[ConsumerRecord[String, String]] = records.iterator()
      while (iter.hasNext) {
        val next: ConsumerRecord[String, String] = iter.next()
        println(s"partition = ${next.partition()}, offset=${next.offset()}\nkey = ${next.key()}, value = ${next.value()}")
        buffer.add(next)
      }
      if(buffer.size()>5){
        // 手动提交offset有两种, 一种是同步阻塞方式, 一种是异步非阻塞方式
        consumer.commitAsync()
        // consumer.commitSync()
        buffer.clear()
      }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值