Kafka概述与工作原理

目录

0、相关文章链接

1、了解Kafka

1.1、Kafka是什么?有什么用?

1.2、kafka的特性

1.3、消息队列有什么用?

2、Kafka的架构

3、操作Kafka集群的两种方式

3.1、使用控制台运行 Kafka

3.2、使用JavaAPI操作Kafka

4、Apache Kafka的工作原理

4.1、分片与副本机制

4.2、消息不丢失机制

4.3、消息存储和查询机制

4.4、生产者数据分发策略

4.5、消费者的负载均衡机制

5、Spring-Kafka

5.1、Spring-Kafka的概述和依赖

5.2、Spring-Kafka生产者示例代码

5.3、Spring-Kafka消费者示例代码

6、Kafka和Kafka-manager


0、相关文章链接

大数据基础知识点 文章汇总

1、了解Kafka

1.1、Kafka是什么?有什么用?

  • 是什么?

    1) Apache Kafka 是一个消息队列(生产者消费者模式)

    2) Apache Kafka 目标:构建企业中统一的、高通量、低延时的消息平台。

    3) 大多的是消息队列(消息中间件)都是基于JMS标准实现的,Apache Kafka 类似于JMS的实现。

  • 有什么用?

    1) 作为缓冲,来异构、解耦系统。

1.2、kafka的特性

  • 消息持久化(Kafka 基于文件系统来存储和缓存消息)。

  • 高吞吐量(Kafka 将数据写到磁盘,但是在底层采用了零拷贝技术,所以速度比较快)。

  • 高扩展性(Kafka 依赖ZooKeeper来对集群进行协调管理,同时在机器扩展时无需将整个集群停机)。

  • 多客户端支持(Kafka 核心模块用Scala 语言开发,但提供多种开发语言接入,包括Java,Python等)。

  • 安全机制(支持代理与ZooKeeper 连接身份验证,客户端读、写权限认证)。

  • 数据备份(Kafka 可以为每个主题指定副本数,对数据进行持久化备份)。

  • 轻量级(Kafka 的实例是无状态的,同时集群本身几乎不需要生产者和消费者的状态信息)。

  • 消息压缩(Kafka 支持Gzip, Snappy 、LZ4 这3 种压缩方式,把多条消息压缩成MessageSet)。

1.3、消息队列有什么用?

  • 解耦,异构

2、Kafka的架构

  • Kafka Cluster:由多个服务器组成。每个服务器单独的名字broker(掮客)。

  • Kafka Producer:生产者、负责生产数据。

  • Kafka consumer:消费者、负责消费数据。

  • Kafka Topic: 主题,一类消息的名称。存储数据时将一类数据存放在某个topci下,消费数据也是消费一样。

  • ZooKeeper:Kafka的元数据都是存放在zookeeper中。

3、操作Kafka集群的两种方式

3.1、使用控制台运行 Kafka

  • 创建一个topic(主题):

    bin/kafka-topics.sh --create --zookeeper zk01:2181 --replication-factor 1 --partitions 1 --topic order

  • 启动一个生产者,用来生产数据 :

    bin/kafka-console-producer.sh --broker-list kafka01:9092 --topic order

  • 启动给一个消费者,消费数据:

    bin/kafka-console-consumer.sh --zookeeper zk01:2181 --from-beginning --topic order

3.2、使用JavaAPI操作Kafka

  • JavaAPI操作Kafka所需要的依赖:

    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>0.11.0.1</version>
  • 生产者相关操作:

    //创建Properties配置参数对象,并设置参数
    Properties props = new Properties();
    props.put("bootstrap.servers", "node01:9092");
    props.put("acks", "all");
    //创建一个KafkaProducer,Kafka生产者对象
    KafkaProducer<String, String> kafkaProducer = new KafkaProducer<String, String>(props);
        for (int i = 0; i < 1000; i++) {
            // 发送数据 ,需要一个producerRecord对象,最少参数 String topic, V value
            kafkaProducer.send(new ProducerRecord<String, String>("order", "订单信息!"+i));
            Thread.sleep(100);
        }  
    }
  • 消费者相关操作:

    // 1、创建配置参数对象,并连接集群
    Properties props = new Properties();
    props.put("bootstrap.servers", "node01:9092");
    props.put("group.id", "test");
    props.put("enable.auto.commit", "true");
    props.put("auto.commit.interval.ms", "1000");
    props.put("key.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
    props.put("value.deserializer","org.apache.kafka.common.serialization.StringDeserializer");
    //2、创建Kafka的消费者对象
    KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<String, String>(props);
    //3、订阅一个主题,订阅主题需传入List格式
    kafkaConsumer.subscribe(Arrays.asList("order"));
    //4、使用死循环不停拉取数据
    while (true) {
        ConsumerRecords<String, String> consumerRecords = kafkaConsumer.poll(100);
        for (ConsumerRecord<String, String> record : consumerRecords) {
            System.out.println("消费的数据为:" + record.value());
        }
    }
  • topic相关操作:

    由于主题的元数据信息是注册在 ZooKeeper 相应节点之中,所以对主题的操作实质是对ZooKeeper中记录主题元数据信息相关路径的操作。Kafka将对ZooKeeper的相关操作封装成一 个ZkUtils 类,井封装了一个AdrninUtils类调用ZkClient类的相关方法以实现对 Kafka 元数据 的操作,包括对主题、代理、消费者等相关元数据的操作。对主题操作的相关API调用较简单,相应操作都是通过调用AdminUtils类的方法来完成的。

    • 创建topic(一般常用方法一):

      方法一:
      //参数:zookeeper的地址,session超时时间,连接超时时间,是否启用zookeeper安全机制
      zkUtils = ZkUtils.apply("node01:2181", 30000, 3000, JaasUtils.isZkSecurityEnabled());
      方法二:
      //参数:zkUtils,topic名称,partition数量,副本数量,参数,机架感知模式
      AdminUtils.createTopic(zkUtils, topicName, 1, 1, new Properties(), AdminUtils.createTopic$default$6());
    • 删除topic:

      //参数:zkUtils,topic名称,partition数量,副本数量,参数,机架感知模式
      AdminUtils.deleteTopic(zkUtils, topicName);
    • 判断是否存在:

      AdminUtils.topicExists(zkUtils, topicName);

4、Apache Kafka的工作原理

4.1、分片与副本机制

  • 分区:当数据量非常大的时候,一个服务器存放不了,就将数据分成两个或者多个部分,存放在多台服务器上。每个服务器上的数据,叫做一个分区。

  • 副本:当数据只保存一份时,有丢失风险。为了更好的容错和容灾,将数据拷贝几份,保存到其他机器上。

  • 设置分区和副本的方法:

    • 控制台上:--replication-factor 1 --partitions 3

    • API代码:AdminUtils.createTopic(zkUtils, topicName, 3, 1, new Properties(),

      AdminUtils.createTopic$default$6());

4.2、消息不丢失机制

  • 生产者消息不丢失机制:

    • 发送消息的同步和异步模式:

      • 同步模式:生产者重试3次,如果还没有响应,就报错。生产者等待10S,如果broker没有给出ack响应,就认为失败。

      • 异步模式:先将数据保存在生产者端的buffer中。Buffer大小是2万条。发送一批数据的大小是500条。满足数据阈值或者数量阈值其中的一个条件就可以发送数据。

    • 消息确认的三个状态:

      • 0状态:生产者只负责发送数据,不管Kafka的broker是否接收到数据;

      • 1状态:某个partition的leader收到数据给出响应;

      • -1状态:某个partition的所有副本都收到数据后给出响应

  • Borker端消息不丢失机制:

    broker端的消息不丢失,其实就是用partition副本机制来保证。Producer ack -1. 能够保证所有的副本都同步好了数据。其中一台机器挂了,并不影像数据的完整性。

  • 消费者端消息不丢失:

    如果有一个外部存储能够记录每个consumer消费partition的offset值。就不会造成数据丢失,只会有重复消费的可能。而在Kafka0.8以后,offset值可以存放到Kafka内置的topic中。

4.3、消息存储和查询机制

4.3.1、消息存储机制

  • Kafka作为消息中间件,只负责消息的临时存储,并不是永久存储,需要删除过期的数据;

  • 如果一个partition中有10T数据,是如何存放的?是存放在一个文件中,还是存放在多个文件中?

    Kafka时采用存储到多个文件中的方式。因为如果将所有数据都存放在一个文件中,需要删除过期数据的时候,就比较麻烦。因为文件有日期属性,删除过期数据,只需要根据文件的日期属性删除就好。

  • Kafka的数据是存储在/export/data/kafka(可以自己设置)目录下,存储时是将数据划分为一个个的segment段,在segment段中有两个核心的文件,一个是log,一个是index。当log文件等于1G时,新的会写入到下一个segment中。

4.3.2、消息查询机制

  • 在Kafka中进行消息查询时,首先会查找segment中的index索引文件,index索引文件是以起始来命名的,根据查询索引文件能很快的定位到具体文件。

  • 当根据index索引文件定位到需要查询的具体文件时,就会去查找log文件,在该文件中按顺序查找到目标文件

4.4、生产者数据分发策略

  • kafka在数据生产的时候,有一个数据分发策略。默认的情况使用DefaultPartitioner.class类。如果用户制定了partition,生产就不会调用DefaultPartitioner.partition()方法。

  • 当用户指定key,就会使用hash算法来确定发往那个patition。如果key一直不变,同一个key算出来的hash值是个固定值。如果是固定值,这种hash取模就没有意义。

    例:Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions

  • 还可以指定将数据发往哪个partition。当ProducerRecord 的构造参数中有partition的时候,就可以发送到对应partition上。

    例:public ProducerRecord(String topic, Integer partition, K key, V value)

  • 如果既没有指定partition,也没有key的情况下,那就使用轮询的方式发送数据。

4.5、消费者的负载均衡机制

一个partition只能被一个组中的成员消费。所以如果消费组中有多于partition数量的消费者,那么一定会有消费者无法消费数据。如果消费组中的消费组小于partition,那么消费的数据就不完整,会造成错误。

5、Spring-Kafka

5.1、Spring-Kafka的概述和依赖

  • 概述:Spring对kafka做了支持,以便简化我们的开发工作,官网:Spring for Apache Kafka

  • 依赖:

    <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
        <version>2.1.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.0.6.RELEASE</version>
    </dependency>    

5.2、Spring-Kafka生产者示例代码

第一步:编写application-kafka-producer.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
​
    <bean id="producerConfig" class="java.util.HashMap">
        <constructor-arg>
            <map>
                <entry key="bootstrap.servers" value="node01:9092,node02:9092"/>
                <!--设置json序列化-->
                <entry key="key.serializer" value="org.springframework.kafka.support.serializer.JsonSerializer"/>
                <entry key="value.serializer" value="org.springframework.kafka.support.serializer.JsonSerializer"/>
            </map>
        </constructor-arg>
    </bean>
​
    <!-- 定义生产者的工厂 -->
    <bean id="producerFactory" class="org.springframework.kafka.core.DefaultKafkaProducerFactory">
        <constructor-arg ref="producerConfig"/>
    </bean>
​
    <!-- 定义KafkaTemplate,通过KafkaTemplate即可实现发送消息等功能 -->
    <bean class="org.springframework.kafka.core.KafkaTemplate">
        <constructor-arg index="0" ref="producerFactory"/>
        <!--指定默认的topic-->
        <property name="defaultTopic" value="my-kafka-topic"/>
    </bean>
​
</beans>

第二步:编写java代码 TestSpringKafkaProducer

//类上方添加如下注释
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:application-kafka-producer.xml"})
//注入一个KafkaTemplate对象
@Autowired
private KafkaTemplate kafkaTemplate;
//使用注入的对象发送数据到Kafka(发送的数据可以是对象,会自动进行json转换)
kafkaTemplate.sendDefault(order);

5.3、Spring-Kafka消费者示例代码

第一步:编写application-kafka-consumer.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="consumerConfig" class="java.util.HashMap">
        <constructor-arg>
            <map>
                <entry key="bootstrap.servers" value="node01:9092,node02:9092"/>
                <entry key="group.id" value="my-group-spring-spring-3"/>
                <entry key="client.id" value="my-test-client-spring-3"/>
                <entry key="enable.auto.commit" value="true"/>
                <entry key="auto.commit.interval.ms" value="1000"/>
                <!--反序列化器,这里要注意设置的是字符串的反序列化-->
                <entry key="key.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>
                <entry key="value.deserializer" value="org.apache.kafka.common.serialization.StringDeserializer"/>
            </map>
        </constructor-arg>
    </bean>

    <!-- 定义消费者的工厂 -->
    <bean id="consumerFactory" class="org.springframework.kafka.core.DefaultKafkaConsumerFactory">
        <constructor-arg ref="consumerConfig"/>
    </bean>

    <!--定义消息监听器,用于接收消息-->
    <bean id="myMessageListener" class="cn.itcast.kafka.MyMessageListener"/>

    <bean id="containerProperties" class="org.springframework.kafka.listener.config.ContainerProperties">
        <!--设置消费的topic,这里可以指定多个topic-->
        <constructor-arg value="my-kafka-topic" type="java.lang.String[]"/>
        <property name="messageListener" ref="myMessageListener"/>
    </bean>

    <!--创建Listener容器-->
        <bean class="org.springframework.kafka.listener.KafkaMessageListenerContainer" init-method="start">
        <constructor-arg index="0" ref="consumerFactory"/>
        <constructor-arg index="1" ref="containerProperties"/>
    </bean>

</beans>

第二步:创建一个类,注入上述配置文件即可接收

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = {"classpath:application-kafka-consumer.xml"})
public class TestSpringKafkaConsumer {
    @Test
    public void testConsumer() {
    }
}

6、Kafka和Kafka-manager

  • Kafka Manager 由 yahoo 公司开发,该工具可以方便查看集群 主题分布情况,同时支持对 多个集群的管理、分区平衡以及创建主题等操作。

  • Kafka和Kafka-manager的详细安装和部署,请详看其安装部署文件。

  • 启动Kafka-manager:

    cd /export/servers/kafka-manager-1.3.3.17/bin ./kafka-manager -Dconfig.file=../conf/application.conf


注:其他相关文章链接由此进 -> 大数据基础知识点 文章汇总


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

电光闪烁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值