大数据开发Kafka入门(第三十八篇)

95 阅读3分钟

一、什么是消息队列

  1. 消息队列(Message Queue)简称MQ
  2. 顾名思义,消息+队列,保存消息的队列
  3. 主要提供生成、消费接口供外部调用做数据的存储和读取
1.1、消息队列分类
  1. 点对点(P2P)

    包含:消息队列(Queue)、发送者(Sender)、接受者(Receiver)

  2. 发布订阅(Pub/Sub)

    包含:消息队列(Queue)、主题(Topic)、发布者(Publisher)、订阅者(Subscriber)

二、什么是Kafka

Kafka是一个高吞吐量的、持久性的、分布式发布订阅消息系统。Kafka主要应用在实时计算领域,可以和Flume、Spark、Flink等框架结合在一块使用。

高吞吐量:可以满足每秒百万级别消息的生产和消费。原理:利用了磁盘顺序读写速度超过内存的随机读写速度

持久性:有一套完善的存储机制,可以确保数据高效安全的持久化

分布式:基于分布式的扩展和容错机制

2.1、Kafka组件介绍
  1. Broker:消息的代理,Kafka集群中的一个节点称为一个Broker
  2. Topic:主题,Kafka处理的消息的不同分类(逻辑概念)
  3. Partition:Topic物理上的分组,一个Topic在Broker中被分为1个或者多个Partition,分区在创建Topic的时候指定,每个Topic都是由分区的,至少1个
  4. Message:消息,是通信的基本单位,每个消息都是属于一个Parrtition
  5. Producer:消息和数据的生产者,向Kafka的Topic生产数据
  6. Consumer:消息和数据的消费者,从Kafka的Topic消费数据

三、Kafka安装部署

  1. Kafka单机安装和集群安装
  2. Kafka需要依赖于Zookeeper
3.1、Zookeeper安装
  1. 官网下载

    zookeeper.apache.org/releases.ht…

  2. 解压压缩包

    tar -zxvf apache-zookeeper-3.8.0-bin.tar.gz

  3. 进入conf目录,修改配置

    mv zoo_sample.cfg zoo.cfg

    修改dataDir属性:dataDir=/root/software/zkData

  4. 启动zookeeper

    bin/zkServer.sh start

  5. 查看启动状态

    bin/zkServer.sh status

3.2、Kafka安装
  1. 官网下载

    kafka.apache.org/downloads

  2. 解压

    tar -zxvf kafka_2.12-3.3.1.tgz

  3. 进入config目录,修改server.properties

    log.dirs 是存储的kafka的核心数据

    log.dirs=/root/software/kafka_2.12-3.3.1/kafka-logs

    zookeeper.connect=localhost:2181 默认链接的是本地的zookeeper。如果不是同一台机器,需要修改下

  4. 启动

    bin/kafka-server-start.sh -daemon config/server.properties

  5. 启动成功之后,使用jps。查看会有kafka进程

  6. 停止

    bin/kafka-server-stop.sh

四、Kafka操作

4.1、Topic操作

新增Topic:指定2个分区,1个副本,副本数不能大于集群中Broker的数量(单机版本)

//这是因为安装的kafka版本过高,2.8+的kafka,已经不需要依赖zookeeper来创建topic,新版本使用 --bootstrap-server 参数

bin/kafka-topics.sh --create --zookeeper localhost:2181 --partitions 2 --replication-factor 1 --topic hello

我这边安装的是2.18版本

bin/kafka-topics.sh --bootstrap-server localhost:9092 --create --topic my-topic --partitions 1

image-20221205144121984

1、查看topic

bin/kafka-topics.sh --list --bootstrap-server localhost:9092

2、修改Topic

修改Topic的Partition数量,只能增加

bin/kafka-topics.sh --bootstrap-server localhost:9092 --alter --topic my-topic --partitions 5

image-20221205144511126

4.4、删除Topic

bin/kafka-topics.sh --bootstrap-server localhost:9092 --delete --topic my-topic

4.2、创建生产者

bin/kafka-console-producer.sh --bootstrap-server localhost:9092 --topic my-topic

image-20221205160436051

4.3、创建消费者

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic my-topic

image-20221205160536732

此时没有反应,因为,kafka默认消费最新生产的数据,也就是消费者起来之后,消费之后的数据

如果要消费之前的数据

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic my-topic --from-beginning

image-20221205162726927

五、代码实战

package com.strivelearn.java.kafka;
​
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
​
import java.util.Properties;
​
/**
 * @author strivelearn
 * @version ProducerDemo.java, 2022年12月05日
 */
public class ProducerDemo {
    public static void main(String[] args) {
        Properties properties = new Properties();
        //指定Kafka的broker地址
        properties.put("bootstrap.servers", "192.168.234.100:9092");
        //指定key-value数据的序列化格式
//        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("key.serializer", StringSerializer.class.getName());
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("acks", "all");
        //创建Kafka生产者
        KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
        //向topic中生产数据
        String topic = "my-topic";
        producer.send(new ProducerRecord<String, String>(topic, "hello java kafka producer"));
        //关闭链接
        producer.close();
    }
}
package com.strivelearn.java.kafka;
​
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
​
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
​
/**
 * @author strivelearn
 * @version ConsumerDemo.java, 2022年12月05日
 */
public class ConsumerDemo {
    public static void main(String[] args) {
        Properties properties = new Properties();
        //指定Kafka的broker地址
        properties.put("bootstrap.servers", "192.168.234.100:9092");
        //指定key-value数据的反序列化格式
        properties.put("key.deserializer", StringDeserializer.class.getName());
        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        //指定消费组
        properties.put("group.id", "con-1");
        //创建Kafka消费者
        KafkaConsumer<String, String> consumer = new KafkaConsumer<>(properties);
        Collection<String> topic = new ArrayList<String>();
        topic.add("my-topic");
        consumer.subscribe(topic);
        while (true) {
            ConsumerRecords<String, String> poll = consumer.poll(Duration.ofSeconds(1));
            for (ConsumerRecord<String, String> stringStringConsumerRecord : poll) {
                System.out.println(stringStringConsumerRecord);
            }
        }
    }
}