Kafka学习(1)-----Kafka初步

思维导图:

引言

    本文主要会在整体上对Kafka进行基础性介绍。所以,总体分为以下三个部分:

  1. 基本概念
  2. 配置安装
  3. 使用JAVA客户端

一.基本概念

    Kafka是一个多分区多副本基于Zookeeper协调的分布式消息系统

1.1 Kafka工作体系

    Kafka的工作体系主要由三大成员构成:

  • 生产者 Producer:负责创建消息并投递到Kafka服务器中
  • 消费者 Consumer:负责接收消息,通过连接到Kafka服务器获取消息并进行相应的逻辑处理
  • 代理 Broker:可以独立的一个服务器,也可以是服务器集群,其作用就是通过Zookeeper为生产者和消费者提供服务并存储数据。

1.2 消息

1.2.1 主题Topic

    消息既是Kafka中主要存储的元数据。由生产者产生,消费者使用。消息通过主题Topic这一概念进行分类。生产者会将 消息发送到特定的主题,而消费者也会订阅主题并进行使用。

1.2.2 分区Partition

    在主题Topic这一层级之下,又将主题Topic分为分区Partition。一个主题可以分为多个分区,每个分区所含有的消息是不同的。主题更多的时一个逻辑上的概念,而分区则可以在存储层面上看做可追加的日志。消息在被追加到特定的分区后都会分配一个偏移量offset作为分区中此消息的唯一标识。Kafka通过偏移量来保证消息在分区内的有序性。

    每一个分区都可以位于不同的代理服务器Broker上,通过设置合理的分配规则,消息可以被均匀的分配到各大分区中,如下图:

    1.2.3 副本Replica

      Kafka引入了多副本Replica以提升容灾能力。一个分区可以拥有多个副本,而副本之间则是一主多从的关系。其中,Leader副本负责处理读写请求,Follower副本负责同步Leader副本内的消息。由Zookeeper的机制可以猜测到主Leader副本和Follower副本之间并不会完全一样,当Leader副本出现问题后,会从Follower副本中重新选举出新的Leader副本。

    在下图所示中,某主题有三个分区,每个分区的副本因子即副本个数为3,所以每个分区有1个Leader副本和2个Follower副本。

    分区中的所有副本称为AR(Assigned Replicas),和Leader副本保持一致的组成ISR(In-Sync Replicas),和Leader之间的消息同步有一定滞后的组成OSR(Out-of Sync Replics),所以 AR = ISR + OSR。

    在ISR中,高水位HW(High Watermark)标志着一个特定的偏移量,代表消费者最多只能拉取到HW之前的消息。因为HW及HW之后的消息可能还未同步。LEO(Log of End Offset)则代表着最新的将要写入的消息所占有的offset。所以ISR中最小的LEO即为整个分区的HW。

    LEO同HW的变化则有如下4图进行演示:

 

二.安装与配置

    在第一节中已经介绍道,Kafka是由Zookeeper提供协调服务的,所以使用Kafka之前需要安装Zookeeper并启动服务器。而Zooke是由Java驱动的,所以还需要安装JDK,这篇文章中就不复述这两者的安装和 使用了,感兴趣的读者可以去我的Zookeeper相关博客中看看。

2.1安装

    下载的时候注意下载二进制的tgz包

//下载
wget http://mirror.bit.edu.cn/apache/kafka/2.2.0/kafka_2.11-2.2.0.tgz
//解压
tar -zxvf kafka_2.11-2.2.0.tgz

2.2 配置

2.2.1 创建集群文件夹

    类似于Redis和Zookeeper集群的创建,在解压了Kafka的安装包后,我们在同级目录下创建只有一台机器的集群演示文件夹。

//kafka集群文件夹创建
mkdir kafka

//9092端口,并创建日志文件夹
mkdir kafka/kafka-9092
mkdir kafka/kafka-9092/log

//9093端口,并创建日志文件夹
mkdir kafka/kafka-9093
mkdir kafka/kafka-9093/log

//9094端口,并创建日志文件夹
mkdir kafka/kafka-9094
mkdir kafka/kafka-9094/log

2.2.2 配置文件修改

    在解压后的Kafka安装包中找到config下的server.properties,复制三份并分别修改其配置

//创建三个配置文件并修改其配置,然后置入对应的文件夹中

//标志Kafka代理服务器Broker的唯一编号
broker.id=0
//客户端监听配置 PLAINTEXT表示协议,//后可以加上ip地址,表示私服内的访问,0.0.0.0表示都可访问,9092表示端口号
listeners=PLAINTEXT://:9092
//公服的客户端监听配置,配置和私服的一个意思
advertised.listeners=PLAINTEXT://192.168.42.128:9092
//日志地址,我们在创建集群文件夹的时候已经创建
log.dirs=/home/zhouhao/kafka/kafka-9092/log
//Zookeeper地址,我已经开启了Zookeeper的服务,没有启动的还需要启动一下
zookeeper.connect=127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183/kafka

broker.id=1
listeners=PLAINTEXT://:9093
advertised.listeners=PLAINTEXT://192.168.42.128:9093
log.dirs=/home/zhouhao/kafka/kafka-9092/log
zookeeper.connect=127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183/kafka

broker.id=2
listeners=PLAINTEXT://:9094
advertised.listeners=PLAINTEXT://192.168.42.128:9094
log.dirs=/home/zhouhao/kafka/kafka-9094/log
zookeeper.connect=127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183/kafka

2.2.3启动服务器

//启动三个服务器,在kafka软件的目录下
bin/kafka-server-start.sh ../kafka/kafka-9092/server-9092.properties
bin/kafka-server-start.sh ../kafka/kafka-9093/server-9093.properties
bin/kafka-server-start.sh ../kafka/kafka-9094/server-9094.properties

2.2.4 检查服务器可用状态

//创建主题
bin/kafka-topics.sh --zookeeper 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183/kafka --create --topic topic-testTopic --replication-factor 3 --partitions 4
//查看主题信息
bin/kafka-topics.sh --zookeeper 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183/kafka --describe --topic topic-testTopic
//消费者订阅主题,脚本使用时无反应,知道生产者脚本产生消息后,就会打印此消息
bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092,127.0.0.1:9093,127.0.0.1:9094 --topic topic-testTopic
//生产者产生主题信息
bin/kafka-console-producer.sh --broker-list 127.0.0.1:9092,127.0.0.1:9093,127.0.0.1:9094 --topic topic-testTopic

 

三.Java客户端的使用

    Linux上的脚本命令毕竟只能作为演示和检验使用,这一节里会使用Java模仿上述例子。

  • maven配置
    <dependencies>
        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka-clients</artifactId>
            <version>2.2.0</version>
        </dependency>

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>
    </dependencies>
  • log4j.properties配置
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

3.1 消费者客户端

/**
 * Kafka 消费者客户端
 *
 * @author : zhouhao
 * @date : Created in 2019/5/20 21:48
 */
public class ConsumerFastStart {
    /**
     * Kafka集群地址
     */
    private static final String BROKE_LIST = "192.168.42.128:9092,192.168.42.128:9093,192.168.42.128:9094";
    /**
     * 主题名称
     */
    private static final String TOPIC_NAME = "topic-testTopic";
    /**
     * 组ID
     */
    private static final String GROUP_ID = "group.demo";

    public static void main(String[] args){
        Properties properties = new Properties();
        properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("bootstrap.servers", BROKE_LIST);
        properties.put("group.id",GROUP_ID);

        KafkaConsumer<String,String> consumer = new KafkaConsumer<>(properties);
        consumer.subscribe(Collections.singletonList(TOPIC_NAME));

        while (true){
            ConsumerRecords<String,String> records = consumer.poll(Duration.ofMillis(1000));
            for(ConsumerRecord<String,String> record : records){
                System.out.println("-----" + record.value());
            }
        }
    }
}

3.2 生产者客户端

/**
 * Kafka 生产者客户端
 *
 * @author : zhouhao
 * @date : Created in 2019/5/20 21:38
 */
public class ProducerFastStart {
    /**
     * Kafka集群地址
     */
    private static final String BROKE_LIST = "192.168.42.128:9092,192.168.42.128:9093,192.168.42.128:9094";
    /**
     * 主题名称
     */
    private static final String TOPIC_NAME = "topic-testTopic";

    public static void main(String[] args){
        Properties properties = new Properties();
        properties.put("bootstrap.servers", BROKE_LIST);
        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

        KafkaProducer<String,String> producer = new KafkaProducer<>(properties);
        ProducerRecord<String,String> record = new ProducerRecord<>(TOPIC_NAME,"Hello,Kafka");

        try{
            producer.send(record);
        } catch (Exception e){
            e.printStackTrace();
        }

        producer.close();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值