kafka知识点梳理

1. kafka定义

  • kafka是分布式的基于发布、订阅模式的消息队列,主要用于大数据实时处理。

2. 消息队列的作用

  • 异步
  • 消峰
  • 解耦

3. 消息队列的两种模式

  • 点对点模式
    • 一对一,生产者生产的消息只能被对应的消费者消费。
    • 数据不进行持久化,消息不能重复消费。
  • 发布/订阅模式
    • 一对多,生产者发布的主题可被多个消费者订阅。
    • 消息持久化,但不是永久,默认一周清理一次。

4. kafka基础架构

  • 为方便扩展,并提高吞吐量,一个topic可以分为多个分区。
  • 配合分区的设计,提出消费组的概念,组内每个消费者进行消费。
  • 为提高可用性,每个partition增加若干副本(leader follower)
  • 相关概念
    • Producer
    • Consumer
    • Consumer Group
    • Broker
    • Topic
    • Partition
    • Replica: 副本
    • leader
    • follower

5. kafka集群配置

  • 修改配置文件
broker.id=0
logs.dir=/opt/kafka/logs
zookeeper.connect=hadoop102:2181,hadoop103:2181
  • 配置环境变量
    • export KAFKA_HOME=
    • export PATH=

6. kafka常用命令

  • kafka-topics.sh 曾删改查topic
    • kafka-topics.sh --zookeeper hadoop102:2181 --cerate --topic first --partitions 3 --replication-factor 2
      创建主题first,分区3,副本数2.
    • kafka-topics.sh --zookeeper hadoop102:2181 --describe --topic first
      主题描述
  • kafka-producer.sh 生产者
    • kafka-producer.sh --topic first --broker-list hadoop101:9092,hadoop102:9092
    • 生产者,指定要发布的节点
  • kafka-console-consumer.sh --topic first --bootstrap-server hadoop102:9092
    • 消费者,指定从哪儿消费
  • kafka-topics.sh --zookeeper hadoop102:2181 --alter --partitions 4 --topic first
    • 修改分区数为4 ,topic的分区数只能增加,不能减少。

7. kafka存储机制

  • 一个topic分为多个partition。
  • 每个partition一个log文件,log文件的特点是可以不停追加。
  • 每个log文件分为多个片(segment),根据大小进行追加。
  • 底层存储的是.log文件和.index文件,.index是协助定位.log文件
    • log文件的命名是以每个segment的第一条消息的offset命名的。
    • index文件的命名与log文件的命名对应,文件内有两列数据,第一列是当前segment的消息序号,
      第二列是每条消息的开头对应的log文件的偏移量。
      • 如何找到offset=3的Message?
        • 首先找到文件,看3处于哪两个文件之间。
        • 3-(文件命名的末尾)得到 index文件中的消息序号,进而得到对应log文件中的偏移量。

8. producer分区原则

  • 分区的好处
    • 方便扩展
    • 提高吞吐量
  • producer发送消息封装的是ProducerRecord对象。
  • 分区原则
    • 在指明partition的情况下,直接将指明的值作为partition的值。
    • 未指明partition但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值
    • 既没有partition值有没有key值的情况下,第一次调用是随机生成一个整数,后面每次调用在这个整数上自增,
      将这个值与topic可用的partition总数取余得到partition值,就是常说的round-robin算法。

9. consumer相关

  • 消费方式
    • pull (kafka采用的方式)根据自己的消费能力拉取数据
    • push
  • 分区分配策略
    • roundrobin (默认采用)
    • range (有可能分配不均)
  • offset维护
    • 0.9版本之前,offset保存在zookeeper中。
    • 0.9版本之后,offset默认保存在kafka一个内置的topic中。

10. 高效读写

  • 顺序写磁盘
  • 零拷贝

11. zookeeper的作用

  • kafka的Controller依赖于zookeeper

12. 异步发送

  • main线程,sender线程,线程共享变量RecordAccmulator。
  public class CustomProducer{
      public static void main(String[] args){
          Properties props = new Properties();
          props.put(ProducerConfig.BOOTSTRAP_SERVER_COINFIG,"hadoop102:9092");
          props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
          props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
          props.put(ProducerConfig.ACKS_CONFIG,"all");
          props.put(ProducerConfig.BATCH_SIZE_CONFIG,16384);
          props.put(ProducerConfig.LINGER_MS_CONFIG,1);

          KafkaProcuder producer = new KafkaProducer<String, String>(props);

          for(int i=0; i < 1000; i++){
              producer.send(new ProducerRecord<String,String>("first",i,"message"+i));
          }

          producer.close();
      }
  }

13. 同步发送

  • 发送一条消息后,会阻塞当前进程,直至返回ack.
  public class SyncProducer(){
      public static void main(String[] args){
          Properties props = new Properties();
            props.put(ProducerConfig.BOOTSTRAP_SERVER_COINFIG,"hadoop102:9092");
            props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
            props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
            props.put(ProducerConfig.ACKS_CONFIG,"all");
            props.put(ProducerConfig.BATCH_SIZE_CONFIG,16384);
            props.put(ProducerConfig.LINGER_MS_CONFIG,1);

            KafkaProcuder producer = new KafkaProducer<String, String>(props);

            for(int i=0; i < 1000; i++){
                RecordMetadata first = producer.send(new ProducerRecord<String,String>("first",i,"message"+i)).get(); //get()方法产生阻塞
                System.out.println("meta="+meta.offset());
            }

            producer.close();
      }
  }

14. 消费者api

  public class CustomConsumer(){
      public static void main(String[] args){
          Properties props = new Properties();
          props.put(ConsumerConfig.BOOTSTRAP_CONFIG_SERVER,"hadoop102:9092");
          props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
          props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class.getName());
          props.put(ConsumerConfig.GOURP_ID_CONFIG,"1205");
          props.put(ConsumerConfig.ENABLE_AUTO_COMMIT,"false");

          KafkaConsumer<String,String> consumer = new KafkaConsumer<>(props);

          consumer.subscribe(Array.asList("first")); //订阅

          while(true){
              ConsumcerRecords<String, String> records  = consumer.pull(100);//超时时间
              for(ConsumerRecord<String,String> record:records){
                  System.out.println("topic=" + record.topic()+"offset="+record.offset()+"value="+record.value());
              }
          }

          consumer.commitAsync(); //异步提交offset
          //consumer.commitSync();//同步提交offset
      }
  }

15. 拦截器

  • kafka的拦截器是拦截器链。
  • 拦截器示例:
  public class TimeInterceptor implements ProducerInterceptor<String,String>{

      private long successNumber = 0;

      private long errorNumber = 0;
      
      @override
      public ProducerRecord<String, String> onSend(ProducerRecord<String,String> record){
          
          //为消息内容加上时间戳
          return new ProducerRecord<String, String>(record.topic(),record.partition(),
                                                    record.timestamp(),record.key(),
                                                    System.currentTimeMillis()+record.value());

      }

      @override
      public void on Acknowledgement(RecordMetadata metadata, Exception exception){

          //统计消息失败次数和成功次数。
          if(exception == null){
              successNumber++;
          }else{
              errorNumber++;
          }
          
      }

      @override
      public void close(){

      }

      @override
      public void configure(Map<String, ?> configs){

      }
      
  }

  //在生产者中指定拦截器即可,多个可用逗号分割
  //props.put(ProducerConfig.INTERCEPTOR_CLASS_CONFIG,"com.xxx.xxx.TimeInterceptor");

16. kafka监控

  • 常用监控工具
    • kafka monitor
    • kafka manager

17. kafka面试题

  • ISR,AR分别是什么?
    • AR:分区副本
    • ISR:保持同步的分区副本
  • HW,LEO分别是什么?
    • 每个分区的最后的offset
    • 所有分区中最后的offset的最小值
  • 怎么体现消息顺序性
    • kafka只能保证分区内有序
    • 要保证所有的消息有序,可以只用一个分区
  • kafka中的分区器,序列化,拦截器的了解以及执行顺序
    • 先拦截器,再序列化,再分区器
  • 生产者客户端的结构是什么样子?用了几个线程来处理?分别是什么?
    • 主线程,sender线程和RecordAccumulator线程共享变量。
  • 消费者个数如果超过topic分区,那么就会有消费者消费不到数据,怎么理解?
    • 正确,一个分区只能被一个消费者消费。
  • 消费者提交消费位移是当前消息的offset还是offset+1?
    • offset+1
  • 哪些情形会造成重复消费?
    • ack=-1的时候
      • follower同步完成,ack未返回leader挂掉,新的leader就会重复消费。
      • 先消费,后提交offset。
  • 哪些情形会造成漏消费?
    • ack = 0 或 1
    • 先提交offset后消费
  • 创建topic的步骤
    • 在zookeeper的broker/topics节点下创建一个新的topic节点
    • 触发Controller监听程序
    • kafka controller负责topic的创建工作,并更新metadata cache.
  • topic的分区数可以增加吗?
    • 可以增加,不可以减少,可以通过alter命令,也可以通过管理工具
  • kafka有内部的topic吗?
    • 有内置的topic
  • 分区分配的概念?
    • roundrobin
    • range
  • kafka controller的作用?
    • 整个kafka集群的管理者
    • 依赖zookeeper来完成
    • leader的选举
    • controller选举等等
  • 什么地方需要选举?
    • controller选举,先到先得
    • leader选举
  • 失效副本是什么?怎么应对?
    • 长时间未与leader同步的副本。
  • kafka 的哪些设计提高性能
    • 分区的概念
    • 顺序写磁盘
    • 零拷贝
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值