kafka快速入门

Kafka快速⼊⻔

1.Kafka的特点

1.解耦:
  允许你独⽴的扩展或修改两边的处理过程,只要确保它们遵守同样的接⼝约束。
2.冗余:
  消息队列把数据进⾏持久化直到它们已经被完全处理,通过这⼀⽅式规避了数据丢失⻛险。许多消息队
列所采⽤的"插⼊-获取-删除"范式中,在把⼀个消息从队列中删除之前,需要你的处理系统明确的指出该消
息已经被处理完毕,从⽽确保你的数据被安全的保存直到你使⽤完毕。
3.扩展性:
  因为消息队列解耦了你的处理过程,所以增⼤消息⼊队和处理的频率是很容易的,只要另外增加处理过
程即可。
4.灵活性 & 峰值处理能⼒:
  在访问量剧增的情况下,应⽤仍然需要继续发挥作⽤,但是这样的突发流量并不常⻅。如果为以能处理
这类峰值访问为标准来投⼊资源随时待命⽆疑是巨⼤的浪费。使⽤消息队列能够使关键组件顶住突发的访问
压⼒,⽽不会因为突发的超负荷的请求⽽完全崩溃。
5.可恢复性:
  系统的⼀部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使⼀个处理
消息的进程挂掉,加⼊队列中的消息仍然可以在系统恢复后被处理。
6.顺序保证:
  在⼤多使⽤场景下,数据处理的顺序都很重要。⼤部分消息队列本来就是排序的,并且能保证数据会按
照特定的顺序来处理。(Kafka 保证⼀个 Partition 内的消息的有序性)
7.缓冲:
  有助于控制和优化数据流经过系统的速度,解决⽣产消息和消费消息的处理速度不⼀致的情况。
8.异步通信:
  很多时候,⽤户不想也不需要⽴即处理消息。消息队列提供了异步处理机制,允许⽤户把⼀个消息放⼊
队列,但并不⽴即处理它。想向队列中放⼊多少消息就放多少,然后在需要的时候再去处理它们。

2.Kafka架构图

在这里插入图片描述
在这里插入图片描述

3.Kafka相关概念

1.producer:
  消息⽣产者,发布消息到 kafka 集群的Borker(下⾯的Leader分区)。
2.broker:
  kafka 集群中安装Kafka的服务器(容器),broker要有唯⼀的ID。
3.topic:
  每条发布到 kafka 集群的消息属于的类别,即 kafka 是⾯向 topic 的(相当于数据库中的表)
4.partition:
  partition 是物理上的概念,每个 topic 包含⼀个或多个 partition。kafka 分配的单位是
partition。
5.consumer:
  从 kafka 集群中消费消息的终端或服务。
6.Consumer group:
  high-level consumer API 中,每个 consumer 都属于⼀个 consumer group,每条消息只能被
consumer group 中的⼀个 Consumer 消费,但可以被多个 consumer group 消费。
7.replica:
  partition 的副本,保障 partition 的⾼可⽤。
8.leader:
  replica 中的⼀个⻆⾊, producer 和 consumer 只跟 leader 交互。
9.follower:
  replica 中的⼀个⻆⾊,从 leader 中复制数据。
10.zookeeper:
  kafka 通过 zookeeper 来存储集群的 meta 信息,并对分区leader做负载均衡

4安装Kafka集群

4.1 安装zookeeper
4.2.安装Kafka集群
上传Kafka安装包
解压
修改配置⽂件
vi servier.properties

#指定broker的id
broker.id=1 #数据存储的⽬录
log.dirs=/data/kafka
#指定zk地址
zookeeper.connect=node-1.51doit.cn:2181,node-2.51doit.cn:2181,node-3.51doit.cn:2181
#可以删除topic的数据(⽣成环境不⽤配置)
#delete.topic.enable=true

将配置好的kafka拷⻉的其他节点
修改其他节点Kafka的broker.id
4.3 启动zk

/bigdata/zookeeper-3.4.13/bin/zkServer.sh start
/bigdata/zookeeper-3.4.13/bin/zkServer.sh status

4.4在所有节点启动Kafka

/bigdata/kafka_2.12-2.4.1/bin/kafka-server-start.sh -daemon /bigdata/kafka_2.12-2.4.1/config/server.properties

4.5查看Kafka进程信息

jps

4.6查看Kafka的topic

/bigdata/kafka_2.12-2.4.1/bin/kafka-topics.sh --list --zookeeper localhost:2181

4.7 创建topic

/bigdata/kafka_2.12-2.4.1/bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic wordcount --replication-factor 3 --partitions 3

4.8启动命令⾏⼀个⽣产者

/bigdata/kafka_2.12-2.4.1/bin/kafka-console-producer.sh --broker-list node-1.51doit.com:9092,node-2.51doit.com:9092,node-3.51doit.com:9092 --topic wordcount

4.8 启动⼀个命令⾏消费者

/bigdata/kafka_2.12-2.4.1/bin/kafka-console-consumer.sh --bootstrap-server node-1.51doit.com:9092,node-2.51doit.com:9092,node-3.51doit.com:9092 --topic wordcount --from-beginning

–from-beginning 消费以前产⽣的所有数据,如果不加,就是消费消费者启动后产⽣的数据
4.9 删除topic

/bigdata/kafka_2.12-2.4.1/bin/kafka-topics.sh --delete --topic wordcount --zookeeper localhost:2181

4.10 查看topic详细信息

/bigdata/kafka_2.12-2.4.1/bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic wordcount

4.11查看某个topic的偏移量

/bigdata/kafka_2.12-2.4.1/bin/kafka-console-consumer.sh --topic __consumer_offsets --bootstrap-server node-1.51doit.com:9092,node-2.51doit.com:9092,node-3.51doit.com:9092 --formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter" --consumer.config /bigdata/kafka_2.12-2.4.1/config/consumer.properties --from-beginning

使用scala代码操作kafka

生产者:

package cn._51doit.kafkaclient

import java.util.{Properties, UUID}

import org.apache.kafka.clients.producer.{KafkaProducer, ProducerRecord}
import org.apache.kafka.common.serialization.StringSerializer

object ProducerDemo {

  def main(args: Array[String]): Unit = {

    // 1 配置参数
    val props = new Properties()
    // 连接kafka节点
    props.setProperty("bootstrap.servers", "node-1.51doit.cn:9092,node-2.51doit.cn:9092,node-3.51doit.cn:9092")
    //指定key序列化方式(ProtoBuf)
    props.setProperty("key.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    //指定value序列化方式
    props.setProperty("value.serializer", classOf[StringSerializer].getName) // 两种写法都行

    //props.setProperty("acks", "1") //ack应答
    //props.setProperty("compression.type", "gzip") //压缩方式
    //props.setProperty("retries", "100") //重试次数
    //props.setProperty("request.timeout.ms", "60000") //超时时间

    val topic = "test"

    // 2 kafka的生产者
    val producer: KafkaProducer[String, String] = new KafkaProducer[String, String](props)

    for (i <- 2021 to 2030) {
      // 3 封装的对象

      //将数据发送到指定的分区编号
      //val record = new ProducerRecord[String, String](topic, 1 , "keyabc","myvalue:"+i)

      //val partitionNum = i % 3  // 指定数据均匀写入3个分区中
      //val record = new ProducerRecord[String, String](topic, partitionNum, null,"myvalue:"+i)


      //不指定分区编号,指定key,   分区编号 = key.hasacode % 3
      //相同key的数据一定会到kafka的同一个分区,但是同一个分区中可以有多个key的数据
      //val record = new ProducerRecord[String, String](topic , "laozhao","myvalue:"+i)


      //根据key的hashcode值模除以topic分区的数量,返回一个分区编号
      val record = new ProducerRecord[String, String](topic , UUID.randomUUID().toString ,"myvalue:"+i)

      //没有指定Key和分区,默认的策略就是轮询,将数据均匀写入多个分区中
      //val record = new ProducerRecord[String, String](topic,"value-" + i)

      // 4 发送消息
      producer.send(record)

    }

    println("message send success")


    // 释放资源
    producer.close()
  }
}

消费者:

package cn._51doit.kafkaclient

import java.time.Duration
import java.util
import java.util.Properties

import org.apache.kafka.clients.consumer.{ConsumerRecords, KafkaConsumer}
import org.apache.kafka.common.serialization.StringDeserializer


//topic、分区、groupId -> 偏移量
object ConsumerDemo {

  def main(args: Array[String]): Unit = {

    // 1 配置参数
    val props = new Properties()
    //从哪些broker消费数据
    props.setProperty("bootstrap.servers", "node-1.51doit.cn:9092,node-2.51doit.cn:9092,node-3.51doit.cn:9092")
    // 反序列化的参数
    props.setProperty("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer")
    props.setProperty("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer")
    // 指定group.id
    props.setProperty("group.id","doit02")

    // 指定消费的offset从哪里开始
    //earliest:从头开始 --from-beginning
    //latest:从消费者启动之后
    props.setProperty("auto.offset.reset","earliest") //[latest, earliest, none]

    // 是否自动提交偏移量  offset
    // enable.auto.commit 默认值就是true【5秒钟更新一次】,消费者定期会更新偏移量 groupid,topic,parition -> offset
    props.setProperty("enable.auto.commit", "false") // 不让kafka自动维护偏移量     手动维护偏移量
    //enable.auto.commit   5000

    // 2 消费者的实例对象
    val consumer: KafkaConsumer[String, String] = new KafkaConsumer[String, String](props)

    // 订阅   参数类型  java的集合
    val topic: util.List[String] = java.util.Arrays.asList("test")

    // 3 订阅主题
    consumer.subscribe(topic)

    while (true){
      // 4  拉取数据
      val msgs: ConsumerRecords[String, String] = consumer.poll(Duration.ofMillis(5000))

      //导入隐式转换
      import scala.collection.JavaConverters._
      //将Java的集合或迭代器转成Scala的集合或迭代器
      for(cr <- msgs.asScala){
          //ConsumerRecord[String, String]
          println(cr)

        //msgs迭代器
        if(msgs.isEmpty) {
          //获取该分区的最大的偏移量
        }
      }
    }

    //consumer.close()

  }
}

总结:

1.Kafka的⽣产者直接向Broker的Leader分区写⼊数据,不需要连接ZK

2.Kafka的消费者(⽼的API需要先连接ZK,获取Broker信息和topic、分区偏移量信息),新的API(0.8以后)不需要
连接ZK(直连⽅式,新的API,底层的API,效率更⾼)

3.kafka叫消息中间件又叫消息队列,具有高可用,高并发,高吞吐,多副本的特点

4.kafka的主从节点体现在borker内的分区,是分区分为主从leader和follower,不是borker,只有leader负责读写数据,leader接收到数据后follower从leader中拉取数据生成副本,当leader挂了之后,follower会挑选出一个新的leader

5.构建topic时分区数量时可以超过节点数量,但副本数量不能超过节点数量

6.一个生成者会默认以轮询的方式通过多个分区leader将数据写入kafka中,但一个消费者只能对接一个leader,避免重复消费,如果消费者数量大于leader数量,那么有的消费者会处于空闲状态,如果小于leader数量,可能某个消费者需要消费多个leader,避免数据丢失,所以最佳方式为消费者数量与节点数量保持一致

7.生成者写入数据时有事务机制,当写入不成功时会回滚,且可以设置写入响应等级ack,ack设置为0是,写入leader后就不管了,不等leader回应是否确定写入成功就直接开始写入下一条,设置为1,等leader回应写入成功后再开始写入下一条,设置为-1为all时,等leader和follower都回应写入成功才开始写入下一条,写入速度越来愈慢,但安全等级越来愈高

8.kafka中有一个自带的topic(_consumer_ofsets),它里面存储着其他topic的分区信息和消费者组的偏移量信息(kafka的偏移量信息是按消费者组为单位进行存储的),它的默认分区数为50个,副本个数一个

9.创建topic时不要使用"_“和”."否则可能会报错

10.当kafka出现负载不均衡时,可能是分区数量设置太少导致的,分区数量建议:节点数量*菜谱核数/预计的topic数量,分区数量创建之后还能进行后续的增添,分区数量太少也可能会导致消费者不能及时消费,造成数据积压

11.生产者按默认的方式进行轮询写入时,不是每来一条数据就写入一次的,是达到一定大小或到达一定时间之后就flush刷入broker

12.解决数据积压和负载不均衡的策略:合理的增加分区的数量,合理的设置flush大小和flush时间,设置合理的retries写入失败重试的次数(默认是int的最大值,不是特别重要的数据可以减少为100次左右),设置压缩格式:lzo/snappy

13.影响偏移量的参数:topic,组id,分区数量,记录偏移量默认是5秒记录一次,那么可能会出现还未记录就消费者挂掉的情况,会导致重复消费数据,所以我们可以自定义记录偏移量的方式,例如将他写入到支持事务的数据库中

14.存数据时,可以支持一条数据的key,当数据都有了key之后,会按key的hashcode值%分区数,将key值相同的数据放入同一个分区当中,但这样可能存在数据倾斜

15.kafka最优的序列化方式:protoBuf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值