目录
- 安装调试
- 基本语法
- Java输入数据
- flume传输文件到kafka
- 补充
安装调试
1、安装包下载:
https://pan.baidu.com/s/1il4pKzJHIOU3wG1BBotmlw 提取码:cd7b
2、解压到虚拟机中指定位置
tar -zxvf kafka_2.11-2.0.0.tgz -C /opt/
3、根据自己需要修改下文件名
mv kafka_2.11-2.0.0/ kafka
4、配置环境变量
#进入profile
vi /etc/profile
#配置环境
export KAFKA_HOME=/opt/kafka
export PATH=$PATH:$KAFKA_HOME/bin
#source生效
source /etc/profile
5、到kafka/config目录下,配置文件
vi server.properties
#broker节点数默认为1,搭集群时配置
broker.id=0
advertised.listeners=PLAINTEXT://192.168.136.10:9092
# 消息存放路径
log.dirs=/opt/kafka/kafka-logs
zookeeper.connect=192.168.136.10:2181
#(手动添加)设置成可以删除topic,默认是不可删的
delete.topic.enable=true
# 注:log.retention.hours=168默认存储7天
6、启动zookeeper
zkServer.sh start
7、启动kafka
kafka-server-start.sh /opt/kafka/config/server.properties
#也可以后台启动
kafka-server-start.sh -daemon /opt/kafka/config/server.properties
8、为了方便以后的启动,给server.properties创建一个软连接
ln -s /opt/kafka/config/server.properties /opt/server.properties
9、测试启动kafka
kafka-server-start.sh -daemon /opt/server.properties
基本语法
创建队列
设置分区数为1,副本数为1。副本数需要小于等于broker,即集群的机器数(zookeeper启动的数),这里如果为2会报错
kafka-topics.sh --create --topic firstDemo
--partitions 1 --replication-factor 1
--zookeeper 192.168.136.30:2181
查看队列
kafka-topics.sh --list --zookeeper 192.168.136.30:2181
查看index和log文件
kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log --print-data-log
查看topic详情
kafka-topics.sh --topic firstDemo --describe
--zookeeper 192.168.136.30:2181
如果创建时定义了多个分区,则如下图所示:
修改partition个数
kafka-topics.sh --alter --topic test --partitions 6 --zookeeper 192.168.136.30:2181
删除队列
kafka-topics.sh --delete --topic secondDemo
--zookeeper 192.168.136.30:2181
创建生产消息
kafka-console-producer.sh --topic firstDemo
--broker-list 192.168.136.30:9092
创建成功后会停留在控制台。
另起一个窗口。
创建消费消息
kafka-console-consumer.sh --topic firstDemo
--bootstrap-server 192.168.136.30:9092 --from-beginning
此时,在生产窗口输入数据,消费窗口会同步更新:
Java输入数据
创建一个新的队列:
kafka-topics.sh --create --topic test1 --partitions 3 --replication-factor 1 --zookeeper localhost:2181
在idea中导入新的依赖包:
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.0.0</version>
</dependency>
生产者:
Properties prop = new Properties();
//连接
prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.136.10:9092");
//序列化配置
prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
prop.put(ProducerConfig.ACKS_CONFIG, "-1");
KafkaProducer<String, String> producer = new KafkaProducer<>(prop);
for (int i = 201; i < 210; i++) {
ProducerRecord<String, String> pr = new ProducerRecord<>("test1", "kafka"+i);
producer.send(pr);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
查看消息队列中每个分区中的数量
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list 192.168.136.10:9092 --topic test1 -time -1 --offsets 1
消费数据
–property print.key=true:打印出key值
kafka-console-consumer.sh --bootstrap-server 192.168.136.10:9092 --topic test1 --from-beginning --property print.key=true
消费者
Properties prop = new Properties();
prop.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.136.10:9092");
prop.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
prop.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
prop.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000");
//是否自动提交
prop.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
prop.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "1000");
//earliest latest none
prop.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest");
prop.put(ConsumerConfig.GROUP_ID_CONFIG, "T1");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(prop);
consumer.subscribe(Collections.singleton("test1"));
while (true) {
ConsumerRecords<String, String> poll = consumer.poll(100);
for (ConsumerRecord<String, String> record : poll) {
System.out.println(record.offset() + " " + record.key() + " " + record.value());
}
}
AUTO_OFFSET_RESET
类型 | 含义 |
earliest | 当各分区下有已提交的offset时,从提交的offset开始消费。没有提交的offset时,从头开始消费 |
latest | 当各分区下有已提交的offset时,从提交的offset开始消费,没有提交的offset时,消费新产生的该分区下的数据 |
none | topic各分区都存在已提交的offset时,从offset后开始消费;只要有一个分区不存在已提交的offset,则抛出异常 |
offset
每条消息在文件中的位置称为offset(偏移量),offset为一个long型的数字,它唯一标记一条消息
多个消费者在同一个分组
Properties prop = new Properties();
prop.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.136.10:9092");
prop.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
prop.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
prop.put(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "30000");
prop.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
prop.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "10000");
prop.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
prop.put(ConsumerConfig.GROUP_ID_CONFIG, "T2");
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(prop);
consumer.subscribe(Collections.singleton("test1"));
while (true) {
ConsumerRecords<String, String> poll = consumer.poll(100);
for (ConsumerRecord<String, String> record : poll) {
System.out.println(Thread.currentThread().getName()+" "+record.offset() + " " + record.key() + " " + record.value());
}
}
}
}).start();
}
flume传输文件到kafka
基于kafka集群
csv数据:
user_id,locale,birthyear,gender,joinedAt,location,timezone
3197468391,id_ID,1993,male,2012-10-02T06:40:55.524Z,Medan Indonesia,480
3537982273,id_ID,1992,male,2012-09-29T18:03:12.111Z,Medan Indonesia,420
823183725,en_US,1975,male,2012-10-06T03:14:07.149Z,Stratford Ontario,-240
1872223848,en_US,1991,female,2012-11-04T08:59:43.783Z,Tehran Iran,210
1、创建conf文件users.conf
users.sources=userSource
users.channels=userChannel
users.sinks=userSink
users.sources.userSource.type=spooldir
users.sources.userSource.spoolDir=/data/flume/dataSourceFile/users/
users.sources.userSource.deserializer=LINE
users.sources.userSource.deserializer.maxLineLength=320000
users.sources.userSource.interceptors=head_filter
users.sources.userSource.interceptors.head_filter.type=regex_filter
users.sources.userSource.interceptors.head_filter.regex=^user_id*
users.sources.userSource.interceptors.head_filter.excludeEvents=true
users.sources.userSource.includePattern=users.csv
users.channels.userChannel.type=file
users.channels.userChannel.checkpointDir=/data/flume/checkpoint/users/
users.channels.userChannel.dataDirs=/data/flume/channelFile/users
users.sinks.userSink.type=org.apache.flume.sink.kafka.KafkaSink
users.sinks.userSink.batchSize=640
users.sinks.userSink.brokerList=192.168.136.30:9092
users.sinks.userSink.topic=users
users.sources.userSource.channels=userChannel
users.sinks.userSink.channel=userChannel
2、创建topic
kafka-topics.sh --create --topic users --partitions 3 --replication-factor 2 --zookeeper localhost:2181
3、执行flume
flume-ng agent --name users --conf /opt/flume/conf/ --conf-file /opt/flume/conf/uses.conf -Dflume.root.logger=INFO,console
4、把文件放入到指定目录下
cp users.csv /data/flume/dataSourceFile/users/users.csv
5、可以通过kafka查看每个分区内的数据量:
查看原数据量:
wc -l users.csv
查看各分区数据量:
kafka-run-class.sh kafka.tools.GetOffsetShell --broker-list 192.168.136.30:9092 --topic users -time -1 --offsets 1
相加为38209,因为去掉了第一行,所以少一行。
6、kafka消费消息
kafka-console-consumer.sh --bootstrap-server 192.168.136.30:9092 --topic users --from-beginning
7、查看队列详情:
kafka-topics.sh --topic users --describe --zookeeper localhost:2181
红色框里指的是各分区数,蓝色框里的0,1,2是各broker的id。server.properties文件中的broker.id。Replica均匀分配在Broker上,同一个partition的replica不会在同一个borker上
补充
kafka的特性
- 消息持久化
- 高吞吐量
- 可扩展性
应用场景
- 消息系统
- 日志系统
- 流处理