kafka常用命令

0、kafka安装

1.1 解压

解压kafka_2.11-2.4.1.tgz至spark目录并重命名为kafka241

1.2 创建日志目录

在kafka241目录下新建文件夹kfklogs

1.3 编辑配置文件

进入config目录,编辑server.properties,在非编辑模式下输入/查找的搜索词然后回车即可跳到相应位置

#四台机器分别为1,2,3,4,依次递增
broker.id=1
#打开侦听端口,每台机器写自己的hostname
listeners=PLAINTEXT://single:9092
#日志存储目录
log.dirs=/opt/software/spark/kafka241/kfklogs
#配置连接zookeeper地址
zookeeper.connect=master01:2181,master02:2181,slave01:2181,slave02:2181/kafka

1、常用命令

1.0 启动关闭命令

server.properties在config目录下,要指定

启动:
kafka-server-start.sh -daemon server.properties
#-daemon是后台启动的意思,默认前台阻塞
#server.properties是指定配置文件
关闭:
kafka-server-stop.sh

1.1 查看主题

#查看主题
kafka-topics.sh --zookeeper master01:2181/kafka --list

1.2 创建主题

#创建主题“first”,分区数为3,备份因子为2
kafka-topics.sh --zookeeper master01:2181/kafka --create --topic first --partitions 3 --replication-factor 2

kafka-topics.sh --create --topic event_attendees_raw --zookeeper single:2181 --replication-factor 1 --partitions 1

1.2.1 自动删除

#删除topic,要现在server.properties里加入这个配置,不过一般不会删除这种东西
delete.topic.enable=true

1.2.2 手动删除

#手工删除topic,使用topic delete
kafka-topics.sh --zookeeper single:2181 --delete --topic event_attendees_raw
#进入kafka-logs目录 删除所有的__consumer_offset_x
#进入zkCli 进入zookeeper rmr删除对应的节点消息

1.3 查看主题的结构描述信息

#查看主题“first”的结构描述信息
kafka-topics.sh --zookeeper master01:2181/kafka --describe --topic first

1.4 进入生产者模式

#生产者模式,生产数据给多个消费者
kafka-console-producer.sh --broker-list master01:9092,master02:9092 --topic first

1.5 进入消费者模式

#消费者模式1,查看生产者发送过来的东西,只看启动生产的数据
#--bootstrap-server:指定kafka服务端,kafka的主机名:端口
kafka-console-consumer.sh --bootstrap-server master01:9092,master02:9092 --topic first
#消费者模式2,查看生产者发送过来的东西,可以看到启动前的数据,从头到尾
kafka-console-consumer.sh --bootstrap-server master01:9092,master02:9092 --topic first --from-beginning

1.6 查看消费者组

#查看消费者组
kafka-consumer-groups.sh --bootstrap-server master01:9092 --list
#console-consumer-71716
#console-consumer-32602
#console-consumer-45272

1.7 查看组详情

#查看组详情
kafka-consumer-groups.sh --bootstrap-server master01:9092 --describe --group console-consumer-????
#输出结果如下:
#GROUP消费者组,TOPIC主题,PARTITION分区,CURRENT-OFFSET当前偏移量,LOG-END-OFFSET下一条将要加入的日志偏移,LAG滞后延时,CONSUMER-ID消费者ID,HOST主机IP,CLIENT-ID客户端

1.8 生产压力测试

#生成压力测试,perf性能
kafka-producer-perf-test.sh --topic first --record-size 1000 --num-records 200000 --throughput -1 --producer-props bootstrap.servers=master01:9092,master02:9092,slave01:9092,slave02:9092
#--topic first 主题
#--record-size 1000 一条消息覆盖的字节
#--num-records 200000 一次性生成多少
#--throughput -1 :定量测延时,不定量测吞吐
#--producer-props 所有的机器

1.9 消费压力测试

#消费压力测试
kafka-consumer-perf-test.sh --topic first --fetch-size 10000 --messages 200000 --threads 1 --broker-list master01:9092,master02:9092,slave01:9092,slave02:9092

1.10 游标位置

#命令:查看读取的游标位置
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list single:9092 --topic event_attendees_raw --time -1
#输出:前面的游标数,后面是总数
mydemo3:0:0

1.11 消费者组offset重置,游标重回earliest

kafka-consumer-groups.sh --bootstrap-server single:9092 --group xym --reset-offsets --all-topics --to-earliest --execute
更新到当前group最初的offset位置
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets --all-topics --to-earliest --execute

更新到指定的offset位置
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets --all-topics --to-offset 500000 --execute

更新到当前offset位置(解决offset的异常)
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets --all-topics --to-current --execute

offset位置按设置的值进行位移
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets --all-topics --shift-by -100000 --execute

offset设置到指定时刻开始
bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --group test-group --reset-offsets --all-topics --to-datetime 2017-08-04T14:30:00.000

1.12 解析查看日志

kafka-dump-log.sh --files ./00000000000000000000.index

1.13、修改分区数(increase)

kafka-topics.sh --zookeeper hd01:2181/kafka --alter --topic mydemo4 --partitions 3

2、查看目录结构

在kafka当中, 每一个topic会有一个单独文件夹, 在topic下会为每一个分区生成一个单独的文件夹, 将这二者合并命名,topic-分区号, 例如test-0, 在每一个分区下又会有多个segment, 既然已经有多个分区了, 为什么要再进行划分为多个segment?

答:①如果只存一个文件中, 文件会越来越大, ②Kafka中的数据默认存储7天, 每一天都会删除7天前的数据, 如果都存在一个文件当中, 会不好删

image-20210118105751733

1.生成测试数据

kafka-producer-perf-test.sh --topic test --num-records 500000 --record-size 1000 --producer-props bootstrap.servers=singleNode:9092 --throughput 1000000000

image-20210118104755487

image-20210118104839561

2.查看index和log文件

kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log --print-data-log

image-20210118105015020

查看偏移量和总数量

kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.index --print-data-log

image-20210118105335288

3、开发经验

3.1 kafka节点数量:

2*(峰值生产速度(MB)*副本数量/100)+1

峰值生产速度向客户提取。如果峰值生产速度:50M/s,副本数,2R/p,那么节点数量为2*(50*2/100)+1=3台。一般集群规模10台,则kafka为3~5台

3.2 Topic数量:

一般情况下,每种日志类型一个topic:行为日志一个,RMDBMS一个

3.3 分区数量:

分区数量是测出来的。创建单分区的topic,测producer和consumer的吞吐速度,假设生产者最小值Tp,消费者最小值为Tc,期望的吞吐为Tt,则分区数为Tt/Math.min(Tp,Tc)。原则是生产消费者的速度都要满足。一般分数区数副本设置根据集群的规模取值3-10个。

image-20210116215245509

image-20210116215748111

4、Kafka工作流程图

image-20210118133026130

5、Kafka API

依赖:

    <!--kafka-->
    <dependency>
      <groupId>org.apache.kafka</groupId>
      <artifactId>kafka-clients</artifactId>
      <version>0.11.0.2</version>
    </dependency>

5.1 Producer API:

package cn.xym.spark

import java.util.Properties

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

object Kafka {
  def main(args: Array[String]): Unit = {
    // 创建配置
    val props = new Properties()
    // 设置Kafka集群
    props.put("bootstrap.servers", "chust01:9092")
    // 设置ack
    // 0: 不需要leader partition确认接收成功, 将消息发送到leader partition即可
    // 1:需要等待leader partition确认接收成功
    // -1(all): 需要等待leader partition以及ISR列表中的follower都确认接收成功
    props.put("acks", "all")
    // 设置key和value的序列化
    props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer")
    props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer")

    // 创建一个Kafka的生产者
    val producer = new KafkaProducer[String,String](props)
    for (elem <- 1 to 100) {
    // 发送消息 三个参数: ①topic, ②key, ③value
    producer.send(new ProducerRecord[String,String]("test","1001","zhangsan"))
    Thread.sleep(10000)
    }
    // 关闭资源
    producer.close()
  }
}
参数名称说明默认值
bootstrap.serverskafka集群的broker-list
acks确保生产者可靠性设置acks=0:不等待成功返回acks=1:等Leader写成功返回acks=all:等Leader和所有ISR中的Follower写成功返回,all也可以用-1代替-1
key.serializerkey的序列化器
value.serializervalue的序列化器
retries发送失败尝试重发次数0
batch.size每个partition的未发送消息大小16384
partitioner.class分区类,可以自定义分区类,实现partitioner接口默认是哈希值%partitions
max.block.ms最大阻塞时长60000

5.2 Consumer API

package cn.xym.spark

import java.util.Properties

import org.apache.kafka.clients.consumer.KafkaConsumer

object KafkaConsumer{
  def main(args: Array[String]): Unit = {
    import org.apache.kafka.clients.consumer.ConsumerRecord
    import org.apache.kafka.clients.consumer.ConsumerRecords
    import java.util
    //创建一个配置
    val props = new Properties()
    //配置Kafka集群的ip和端口号
    props.put("bootstrap.servers", "chust01:9092")
    //设置消费者组的id,如果有多个相同id的消费者程序,那么他们将在一个组中
    props.put("group.id", "testGroup1")
    //开启自动提交,默认是开启
    props.put("enable.auto.commit", "true") //默认值true
    //默认每隔5000ms提交一次
    props.put("auto.commit.interval.ms", "1000") //默认值5000
    //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")
    consumer.subscribe(topics)
    //为了能够一直从Kafka中消费数据,使用while死循环
    while (true){
      //拉取数据,kafka推过来的一堆数据
      val records = consumer.poll(1000)
      //对这些数据转化为迭代器进行遍历输出
      val iter = records.iterator()
      while (iter.hasNext){
        val next = iter.next()
        println(s"partition = ${next.partition()},offset = ${next.offset()},value = ${next.key()},value = ${next.value()}")
      }
    }
  }
}

5.3 Consumer Offset API 偏移

package cn.xym.spark

import java.util
import java.util.Properties

import org.apache.kafka.clients.consumer.{ConsumerRecord, ConsumerRecords, KafkaConsumer}

object KafkaConsumer2 {
  def main(args: Array[String]): Unit = {
    // 创建一个配置
    val props = new Properties()
    // 配置Kafka集群的ip和端口号
    props.put("bootstrap.servers", "chust01: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 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()
      }

    }
  }
}

onsumerRecord[String, String] = iter.next()
println(s"partition = n e x t . p a r t i t i o n ( ) , o f f s e t = {next.partition()}, offset= 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、付费专栏及课程。

余额充值