Kafka(一)

hadoop实时day22–Apache Kafka


今日内容大纲
1、消息队列 MQ
	模式:点对点  发布订阅
	使用场景、好处
2、Apache kafka 介绍
	分布式存储消息队列
3、Apache Kafka集群组件 名词
4、Apache Kafka集群搭建 
5、Apache kafka工作流程-整体
6、Apache kafka 操作
	shell基础操作
	java api 操作
		生产者代码
		消费者代码
7、Apache kafka 分区 副本机制		

消息队列
  • 基本概念

    • 消息:应用程序之间通信传输的数据。
    • 队列:先进先出的数据结构。队列能够保证消息的顺序的。
    • ==消息队列:Message Queue。简称MQ.==是应用程序之间进行通信的一种方式,可以简单理解为把要传递的消息数据放置在队列中。
    • 消息中间件:实现消息队列功能的软件。
    • 在java语系中,有一个规范JMS(Java Message Service).描述了消息队列应该具备何种属性何种模型。
      • 上面上大多数软件都遵循了JMS规则:ActiveMQ …
      • Kafka没有遵循JMS规范。在功能实现上靠近JMS。
  • 消息队列应用场景

    • 异步处理

    • 系统解耦

    • 流量削峰

    • 大数据领域作为数据源 数据传输存储的中间件

      数据源---->kafka---->spark streaming|flink
      
  • 消息队列模型–生产者消费模型

    • 点对点模式

      p2p模型 一对一的模型
      
    • 发布订阅模式

      一对多 甚至多对多模型。
      
      topic:消息的不同分类。对消息进行划分。
      
      生产者:发布消息要指定消息所属的主题。
      消费者:在消费消息之前必须定义主题 消费指定的主题。
      

Apache kafka
  • kafka介绍

    Apache Kafka是一个分布式流平台。一个分布式的流平台应该包含3点关键的能力:
    1. 发布和订阅流数据流,类似于消息队列或者是企业消息传递系统
    2. 以容错的持久化方式存储数据流
    3. 处理数据流
    
    • 当下企业中核心功能还是两个。 分布式消息队列(发布订阅模型) 数据存储
    • 未来kafka致力于成为流处理平台 参与实时计算分析领域。
    • 核心:kafka集群、生产者、消费者。
    • kafka来自于linkedin公司,用于解决linkedin内部消息传递问题。现属于Apache .
    • kafka底层是使用scala和java语言实现的。
  • kafka优点

    • 分布式

      多台机器存储。 解决了消息数据存储不下的问题。
      
    • 副本机制

      保证了数据安全 可用。
      
    • 高并发

    • API 开发规范成熟。

    • 支持消息存储 持久化。

      某种程度上kafka也是一个大数据存储软件。
      

kafka 组件、集群结构
  • kafka是一个分布式集群软件。

  • zookeeper集群

    当下kafka运行需要依赖zk集群。管理kafka的元数据。
    
  • broker

    在每台机器上运行的kafka进程,叫做broker.称之为kafka代理。
    多个broker就组成了kafka集群。
    
  • producer

    生产者。负责将数据写入kafka集群的主题中。必须指定主题。
    
  • consumer group

    消费者组。多个消费者可以组成一个组 共同订阅主题进行消费。
    消费者组存在某种程度上还实现了消费者容错机制。一个消费者出了问题。组内其他消费者可以继续代替消息。
    
  • consumer

    消费者。订阅主题消费数据。
    通过不断轮询拉取自己订阅的主题消息。
    
  • topic

    消息的主题。对消息按类别进行划分归类。 比如:OrderTopic  UserTopic
    在发送消息 处理的消息必须要指定消息主题。
    
    • partition

      主题的分区。为什么要把主题分区?解决了一台机器存储不下的问题。
      把一个主题的消息进行分区之后 不同的分区就可以存储在kafka不同的broker。
      
    • Replicas

      分区的副本,备份。 为什么要备份? 解决了机器故障导致分区数据容易丢失的问题。
      
      所有的副本中分为两类:
      	leader副本:只有leader才会负责生产者消费者读写请求。
      	follower副本:只用于同步leader副本的数据。 当leader挂掉之后 成为leader提供服务。容错。
      
  • offset

    偏移量。
    在一个分区中,消息是有顺序的方式存储着,每个在分区的消费都是有一个递增的id。这个就是偏移量offset。
    
    注意:在分区中 可以保证消息顺序  全局无法保证有序
    如果想要消息全局有序?可以把消息分区设置为1. 
    
    此外这个offset还影响着消费者从哪里消费数据。可以指定位置读取消息进行消费。
    

Kafka集群搭建
  • 前提:因为kafka依赖zk保存一些元数据。在启动kafka之前保证zk集群启动且服务可用

  • 注意:kafka的消息是直接存储在linux系统上的。所以不需要依赖hadoop。

  • 安装包

    kafka_2.11-1.0.0.tgz
    
    #注意 2.11指的scala版本号。
    
  • 上传解压

  • 修改配置文件

    • /export/servers/kafka/config/server.properties

      #brokerid 不重复 大于等于0(每台机器不一样)
      broker.id=0
      #kafka消息存储路径
      log.dirs=/export/data/kafka
      #zk集群地址
      zookeeper.connect=node-1:2181,node-2:2181
      #是否允许直接删除主题数据
      delete.topic.enable=true
      #当前机器的主机名(每台机器不一样)
      host.name=node-1
      #对外暴露的协议(每台机器不一样)
      listeners=PLAINTEXT://node-1:9092
      
  • scp安装包给其他机器

  • 拷贝后, 需要修改每一台的==broker.id 和 host.name和listeners==

  • kafka集群启动

    kafka集群启动之前 必须先启动zk集群。 sh startZk.sh

    #前端启动
    bin/kafka-server-start.sh config/server.properties
    
    #后台启动:
    bin/kafka-server-start.sh -daemon config/server.properties
    
    #作业
    根据之前的一键启动zk的脚本改写一键启动kafka.
    
    #关闭
    bin/kafka-server-stop.sh 
    

image-20210331221458383

Kafka shell操作
  • 创建主题

    bin/kafka-topics.sh --create --topic test1 --partitions 3 --replication-factor 2 --zookeeper node-1:2181,node-2:2181
    
    --create  #表示创建主题
    --topic  #主题的名称
    --partitions #主题分区个数
    --replication-factor #主题每个分区副本数
    --zookeeper  
    
  • 列出当前所有主题

    bin/kafka-topics.sh --list  --zookeeper node-1:2181,node-2:2181
    
  • 查看主题的详细信息

    bin/kafka-topics.sh --describe --topic test1  --zookeeper node-1:2181,node-2:2181
    
    Topic:test1     PartitionCount:3        ReplicationFactor:2     Configs:
            Topic: test1    Partition: 0    Leader: 0       Replicas: 0,1   Isr: 0,1
            Topic: test1    Partition: 1    Leader: 1       Replicas: 1,2   Isr: 1,2
            Topic: test1    Partition: 2    Leader: 2       Replicas: 2,0   Isr: 2,0
    
  • 增加、修改主题的配置

    bin/kafka-topics.sh --zookeeper node01:2181 --alter --topic test --config flush.messages=1
    bin/kafka-topics.sh --zookeeper node01:2181 --alter --topic test --delete-config flush.messages
    将flush.messages设置为1,那么每一条消息都会刷盘。
    
  • 删除主题

    delete.topic.enable=true
    然后执行以下命令进行删除topic
    
    bin/kafka-topics.sh --delete --topic test2  --zookeeper node-1:2181,node-2:2181
    
    Topic test2 is marked for deletion.
    Note: This will have no impact if delete.topic.enable is not set to true.
    
  • 增加分区

    bin/kafka-topics.sh --zookeeper node-1:2181,node-2:2181 --alter --topic test1 --partitions 5
    
    #把test1主题 分区修改为5  之前是3
    
    WARNING: If partitions are increased for a topic that has a key, the partition logic or ordering of the messages will be affected
    Adding partitions succeeded!
    #增加分区的个数是允许的操作 但是要注意可能会影响生产者发送策略 基于key % 分区个数 
    
    
    #能不能减少分区个数呢?
    bin/kafka-topics.sh --zookeeper node-1:2181,node-2:2181 --alter --topic test1 --partitions 2
    
    #日志显示 减少分区操作是不允许 失败
    Error while executing topic command : The number of partitions for a topic can only be increased. Topic test1 currently has 5 partitions, 2 would not be an increase.
    
    #kafka为什么不允许减少分区。
    着重考虑被删除的分区的数据该如何处理 而不影响已有分区数据安全、顺序问题。
    
  • producer生产消息到kafka

    • 命令

      kafka-console-consumer.sh
      
    • 用法

      bin/kafka-console-producer.sh --broker-list node-1:9092 --topic test1
      
  • consumer读取kafka消息消费

    • 命令

      kafka-console-producer.sh
      
    • 用法

      bin/kafka-console-consumer.sh --topic test1 --bootstrap-server node-1:9092 --from-beginning 
      
      --bootstrap-server  #指定kafka集群地址  老版本中是指定zk集群地址  
      在老版本中 消费者消费记录offset是保存在zk中  新版本中kafka为了脱离zk 自己保存消费记录。
      
      --from-beginning  #详细解释见画图
      

Kafka java API
  • 开发环境准备

  • 官方api地址:http://kafka.apache.org/21/javadoc/

  • 生产者

    • 核心类 KafkaProducer

    • 消息核心类 ProducerRecord

          private final String topic;   //主题
          private final Integer partition; //分区
          private final Headers headers;   //头信息
          private final K key;             //消息的key 默认为空 如果有值 影响分区策略
          private final V value;           //消息内容
          private final Long timestamp;    //时间戳
      
      • 在kafka中数据也是以kv形式存在的。其中v重要 保存消息数据

      • kv在底层都是以==bytes[]==形式存在的。意味着在写数据读数据的时候 需要进行类型转换。

        kafka需要指定序列化类 和反序列化的类。
        如果把数据从各个类型序列化成为bytes[]
        
        在kafka中 使用最多的类型是String
        
      • 配置对象类 ProducerConfig

        • 核心参数

          • ACK机制 后面知识点说

          • retries 重试次数

            retries 		 //生产者的重试次数 默认0
            retry.backoff.ms //两次重试之间的时间间隔 默认100ms
            
  • 消费者

    • 核心类 KafkaConsumer

      • 注意事项

        #创建消费者要指定消费者所属的消费者组。
        
        #消费数据之前首先订阅主题。
        	猜想:能否只消费主题中某个分区数据?
        	猜想:能否指定从什么位置消费呢?
        	
        #消费的过程是一个拉模式的过程。消费者不断轮询拉取自己订阅的消息。
        
        #消费者需要提交自己的消费记录 消费偏移量offset
        	消费记录保存在哪里?
        		老版本中:保存在zk集群中。
        		新版本中:kafka内置的主题:__consumer_offsets  默认有50个分区。
        		还可以自己存储在外部介质中:比如mysql  redis。(Spark Streaming)
        
    • 消费者配置核心类==ConsumerConfig==

    • 消费者

      • 自动提交消费偏移量

      • 手动提交消费偏移量–批处理提交,不是一个一个提交。

             Properties props = new Properties();
             props.put("bootstrap.servers", "localhost:9092");
             props.put("group.id", "test");
             props.put("enable.auto.commit", "false"); //关闭自动提交
             props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
             props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
             KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
             consumer.subscribe(Arrays.asList("foo", "bar"));
             final int minBatchSize = 200; //定义缓存大小
             List<ConsumerRecord<String, String>> buffer = new ArrayList<>(); //用于缓存消息
             while (true) {
                 ConsumerRecords<String, String> records = consumer.poll(100);
                 for (ConsumerRecord<String, String> record : records) {
                     buffer.add(record);//把拉取过来的数据添加到集合缓存中
                 }
                 if (buffer.size() >= minBatchSize) {//当满足大小的时候 
                     
                     insertIntoDb(buffer);// 执行相关的业务操作
                     
                     consumer.commitSync();//处理完数据之后 手动提交
                     buffer.clear(); //清空缓存 便于下次处理数据
                 }
             }
        
      • 手动提交消费offset存储在外部介质中。

        后续课程中Spark Streaming中使用mysql自己来存储offset 确保精准一次性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

章鱼哥TuNan&Z

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

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

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

打赏作者

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

抵扣说明:

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

余额充值