kafka高频面试记录

零、kafka为什么快

https://www.cnblogs.com/lazyegg/p/13501809.html
Kafka速度的秘诀在于,它把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗,通过mmap提高I/O速度,写入数据的时候由于单个Partion是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出。因此,kafka实现高速传输的原因有一下五点:

1. partition 并行处理

kafka按照Topic 区分数据。每个 Topic 都包含一个或多个 Partition,不同 Partition 可位于不同节点。
一方面,由于不同 Partition 可位于不同机器,因此可以充分利用集群优势,实现机器间的并行处理。
另一方面,由于 Partition 在物理上对应一个文件夹,即使多个 Partition 位于同一个节点,也可通过配置让同一节点上的不同 Partition 置于不同的磁盘上,从而实现磁盘间的并行处理,充分发挥多磁盘的优势。

2. 顺序写磁盘,充分利用磁盘特性

Kafka 中每个分区是一个有序的,不可变的消息序列,新的消息不断追加到 partition 的末尾,这个就是顺序写。
kafka在清除旧数据时,会将partition分为多个segment。每个 Segment 对应一个物理文件,通过删除整个文件的方式去删除 Partition 内的数据。这样也避免了对kafka随机写的操作。

3.利用了现代操作系统分页存储 Page Cache 来利用内存提高 I/O 效率

Cache 层的目的是为了提高 Linux 操作系统对磁盘访问的性能。Cache 层在内存中缓存了磁盘上的部分数据。当数据的请求到达时,如果在 Cache 中存在该数据且是最新的,则直接将数据传递给用户程序,免除了对底层磁盘的操作,提高了性能。
在 Linux 的实现中,文件 Cache 分为两个层面,一是 Page Cache,另一个 Buffer Cache,每一个 Page Cache 包含若干 Buffer Cache。Page Cache 主要用来作为文件系统上的文件数据的缓存来用,尤其是针对当进程对文件有 read/write 操作的时候。Buffer Cache 则主要是设计用来在系统对块设备进行读写的时候,对块进行数据缓存的系统来使用。

4. 采用了零拷贝技术

零拷贝(Zero-copy)技术指在计算机执行操作时,CPU 不需要先将数据从一个内存区域复制到另一个内存区域(比如内核空间和用户空间),从而可以减少上下文切换以及 CPU 的拷贝时间。
传统的 Linux 系统中,标准的 I/O 接口(例如read,write)都是基于数据拷贝操作的,即 I/O 操作会导致数据在内核地址空间的缓冲区和用户地址空间的缓冲区之间进行拷贝,所以标准 I/O 也被称作缓存 I/O。这样,无论是produce还是consume数据都会发生四次拷贝。

1. 网络数据持久化到磁盘子( Producer 生产的数据持久化到 broker,采用 mmap 文件映射,实现顺序的快速写入)
传统:

  • 首先通过 DMA(DMA(Direct Memory Access):直接存储器访问。) copy 将网络数据拷贝到内核态 Socket Buffer
  • 然后应用程序将内核态 Buffer 数据读入用户态(CPU copy)
  • 接着用户程序将用户态 Buffer 再拷贝到内核态(CPU copy)
  • 最后通过 DMA copy 将数据拷贝到磁盘文件
    在这里插入图片描述
    kafka:使用mmp将数据写入磁盘,直接略过用户缓存区实现三次拷贝
    Memory Mapped Files:简称 mmap,也有叫 MMFile 的,使用 mmap 的目的是将内核中读缓冲区(read buffer)的地址与用户空间的缓冲区(user buffer)进行映射。从而实现内核缓冲区与应用程序内存的共享,省去了将数据从内核读缓冲区(read buffer)拷贝到用户缓冲区(user buffer)的过程。它的工作原理是直接利用操作系统的 Page 来实现文件到物理内存的直接映射。完成映射之后你对物理内存的操作会被同步到硬盘上。
    在这里插入图片描述
    2. 磁盘文件通过网络发送(Customer 从 broker 读取数据,采用 sendfile,将磁盘文件读到 OS 内核缓冲区后,转到 NIO buffer进行网络发送,减少 CPU 消耗)
    传统——四次拷贝
  • 首先通过系统调用将文件数据读入到内核态 Buffer(DMA 拷贝)
  • 然后应用程序将内存态 Buffer 数据读入到用户态 Buffer(CPU 拷贝)
  • 接着用户程序通过 Socket 发送数据时将用户态 Buffer 数据拷贝到内核态 Buffer(CPU 拷贝)
  • 最后通过 DMA 拷贝将数据拷贝到 NIC Buffer
    kafka——使用sendfile,实现两次拷贝
  • sendfile系统调用,文件数据被copy至内核缓冲区
  • 再从内核缓冲区copy至内核中socket相关的缓冲区
  • 最后再socket相关的缓冲区copy到协议引擎
    在这里插入图片描述

5.批量压缩

在很多情况下,系统的瓶颈不是CPU或磁盘,而是网络IO

  1. 如果每个消息都压缩,但是压缩率相对很低,所以Kafka使用了批量压缩,即将多个消息一起压缩而不是单个消息压缩;
  2. Kafka允许使用递归的消息集合,批量的消息可以通过压缩的形式传输并且在日志中也可以保持压缩格式,直到被消费者解压缩;
  3. Kafka支持多种压缩协议,包括Gzip和Snappy压缩协议

一、kafka可靠性(高可用性)

https://www.cnblogs.com/PigeonNoir/articles/11043542.html
kaaka里的可靠性可理解为高可用性,即指系统无间断地执行其功能的能力,代表系统的可用性程度

1.分区副本 leader和follower

Kafka 的分区多副本架构是 Kafka 可靠性保证的核心,把消息写入多个副本可以使 Kafka 在发生崩溃时仍能保证消息的持久性。

Kafka 可以保证单个分区里的事件是有序的,分区可以在线(可用),也可以离线(不可用)。在众多的分区副本里面有一个副本是 Leader,其余的副本是 follower,所有的读写操作都是经过 Leader 进行的,同时 follower 会定期地去 leader 上的复制数据。当 Leader 挂了的时候,其中一个 follower 会重新成为新的 Leader。通过分区副本,引入了数据冗余,同时也提供了 Kafka 的数据可靠性。

2. ISR表

每个分区的 leader 会维护一个 ISR 列表,ISR 列表里面就是 follower 副本的 Borker 编号,只有跟得上 Leader 的 follower 副本才能加入到 ISR 里面
当 Leader 挂掉了,而且 unclean.leader.election.enable=false 的情况下,Kafka 会从 ISR 列表中选择第一个 follower 作为新的 Leader,因为这个分区拥有最新的已经 committed 的消息。通过这个可以保证已经 committed 的消息的数据可靠性。
需要配置的参数:
producer 级别:acks=all(或者 request.required.acks=-1),同时发生模式为同步 producer.type=sync
topic 级别:设置 replication.factor>=3,并且 min.insync.replicas>=2;
broker 级别:关闭不完全的 Leader 选举,即 unclean.leader.election.enable=false;

3. ACK消息确认机制

https://www.cnblogs.com/PigeonNoir/articles/11043542.html
Kafka 在 Producer 里面提供了消息确认机制。也就是说我们可以通过配置来决定消息发送到对应分区的几个副本才算消息发送成功。Producer 时通过 acks 参数指定,主要有三种值:

  1. ack =0
    如果生产者能够通过网络把消息发送出去,那么就认为消息已成功写入 Kafka 。
    优点:吞吐量和带宽利用率很高
    缺点:发送的对象没能够被序列化或者网卡发生故障,或者是分区离线或整个集群长时间不可用,不会收到任何错误。这时候会丢失数据
  2. ack=1
    若 Leader 在收到消息并把它写入到分区数据文件(不一定同步到磁盘上)时会返回确认或错误响应。不考虑follower有没有备份完成。
    优点:一定程度上减少数据丢失问题
    缺点:仍可能会有数据丢失的情况发生。如,消息已经成功写入 Leader,但在消息被复制到 follower 副本之前 Leader发生崩溃。
  3. ack=all/-1
    不仅要leader收到消息写入本地log,还要等所有ISR集合中的follower都备份完成后,producer才认为发送成功。
    优点:数据不丢失;
    缺点:吞吐量大大降低
    在这里插入图片描述

4. 故障恢复

https://zhuanlan.zhihu.com/p/363082581#:~:text=%E3%80%8C%E3%80%8C%E9%AB%98%E5%8F%AF%E7%94%A8%E6%80%A7%E3%80%8D%E3%80%8D,%EF%BC%8C%E6%8C%87%E7%B3%BB%E7%BB%9F%E6%97%A0%E9%97%B4%E6%96%AD%E5%9C%B0%E6%89%A7%E8%A1%8C%E5%85%B6%E5%8A%9F%E8%83%BD%E7%9A%84%E8%83%BD%E5%8A%9B%EF%BC%8C%E4%BB%A3%E8%A1%A8%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%8F%AF%E7%94%A8%E6%80%A7%E7%A8%8B%E5%BA%A6%20Kafka%E4%BB%8E0.8%E7%89%88%E6%9C%AC%E5%BC%80%E5%A7%8B%E6%8F%90%E4%BE%9B%E4%BA%86%E9%AB%98%E5%8F%AF%E7%94%A8%E6%9C%BA%E5%88%B6%EF%BC%8C%E5%8F%AF%E4%BF%9D%E9%9A%9C%E4%B8%80%E4%B8%AA%E6%88%96%E5%A4%9A%E4%B8%AABroker%E5%AE%95%E6%9C%BA%E5%90%8E%EF%BC%8C%E5%85%B6%E4%BB%96Broker%E8%83%BD%E7%BB%A7%E7%BB%AD%E6%8F%90%E4%BE%9B%E6%9C%8D%E5%8A%A1

  1. 首先需要在集群所有Broker中选出一个Controller,负责各Partition的Leader选举以及Replica的重新分配。当出现Leader故障后,Controller会将Leader/Follower的变动通知到需为此作出响应的Broker。
  2. Kafka使用ZooKeeper存储Broker、Topic等状态数据,Kafka集群中的Controller和Broker会在ZooKeeper指定节点上注册Watcher(事件监听器),以便在特定事件触发时,由ZooKeeper将事件通知到对应Broker

二、kafka的一致性

https://www.cnblogs.com/PigeonNoir/articles/11043542.html
High Water Mark 机制
kafk的HW标记了分区中被充分备份过的(fully replicated)消息的位移。因此kafka的HW主要有两个作用:
1、用于实现副本备份机制(replication);
2、定义消息可见性,即HW之下的所有消息对consumer是可见的。
在这里插入图片描述

三、kafka保证不重复消费

1. 内部保证

https://cloud.tencent.com/developer/article/1665700
kafka重复消费的本质是,已经消费了数据,但是offset没来得及提交。总结一下场景可能会导致kakfa重复消费:

  • 强行kill线程,导致消费后的数据,offset没有提交(消费系统宕机、重启等)。
  • 设置offset为自动提交,关闭kafka时,如果在close之前,调用 consumer.unsubscribe() 则有可能部分offset没提交,下次重启会重复消费。
    **解决方案:**设置offset自动提交为false,这是因为一旦设置了 enable.auto.commit 为 true,Kafka 会保证在开始调用 poll 方法(poll方法呢你穿的参数是时间ms,例如poll(5000): 如果拉到数据的话 会立即放回;如果拉不到数据的话,这个是最长的等待时间)时,提交上次 poll 返回的所有消息。从顺序上来说,poll 方法的逻辑是先提交上一批消息的位移,再处理下一批消息,因此它能保证不出现消费丢失的情况。
    api的设置方案如下:
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "false");
  • rebalance导致的重复消费,具体情况如下:
  • (重复消费最常见的原因):消费后的数据,当offset还没有提交时,partition就断开连接。比如,通常会遇到消费的数据,处理很耗时,导致超过了Kafka的session timeout时间(0.10.x版本默认是30秒),那么就会re-blance重平衡,此时有一定几率offset没提交,会导致重平衡后重复消费。
  • 当消费者重新分配partition的时候,可能出现从头开始消费的情况,导致重发问题。
  • 消费者消费数据很慢或者并发量很高的情况下,都可能导致数据在同一个seesion内还没消费完,进而可能导致rebalance,导致一部分offset自动提交失败,然后重平衡后重复消费
    解决方案是:
    https://blog.csdn.net/YoungLee16/article/details/87103634
  • 调整seession-time和maxpollrecordsconfig的值
    最优化的方程式是: maxpollrecordsconfig/代码处理单条数据时间=session-time.
    注:session-time指的是kakfa数据一次poll的时间;maxpoolrecordsconfig指的是一次进行poll的数据量大小

2. 与flink交互

https://www.cnblogs.com/smartloli/p/11922639.html
1. offset机制

这个可以和flink结合使用,将消费的kakfa的offset保存到flink的state中,每次消费前判断下state

2. 幂等性

  • 什么是幂等性
    幂等性指的是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
  • 如何实现幂等性
  • ProducerID和SequenceNumber
    ProducerID:在每个新的Producer初始化时,会被分配一个唯一的ProducerID,这个ProducerID对客户端使用者是不可见的。
    SequenceNumber:对于每个ProducerID,Producer发送数据的每个Topic和Partition都对应一个从0开始单调递增的SequenceNumber值。
  • kakf的事务性
    事务性Kafka中的produce端事务属性是指一系列的Producer生产消息和消费消息提交Offsets的操作在一个事务中,即原子性操作。对应的结果是同时成功或者同时失败。

四、kafka的有序性

https://www.jianshu.com/p/82d473397cbf

1.多partition有序

Kafka引入了Producer ID(即PID)和Sequence Number。对于每个PID,该Producer发送消息的每个<Topic, Partition>都对应一个单调递增的Sequence Number。同样,Broker端也会为每个<PID, Topic, Partition>维护一个序号,并且每Commit一条消息时将其对应序号递增。对于接收的每条消息,如果其序号比Broker维护的序号)大一,则Broker会接受它,否则就丢弃

2.单partiton的有序性

message.key的同一key放到一个partition里,这样由于offset机制,会实现有序性

五、kafka的脑裂问题

1.什么是脑裂问题

https://www.jianshu.com/p/8f24fb9b7515
kafka中只有一个控制器controller 负责分区的leader选举,同步broker的新增或删除消息,但有时由于网络问题,可能同时有两个broker认为自己是controller,这时候其他的broker就会发生脑裂,不知道该听从谁的。

2.解决方法

controller epoch
每当新leader产生时,会生成一个epoch,这个epoch是递增的,followers如果确认了新的leader存在,知道其epoch,就会拒绝epoch小于现任leader epoch的所有请求。具体机制如下:
· 所有Broker监控"/controller",节点被删除则开启新一轮选举,节点变化则获取新的epoch
· Controller会注册SessionExpiredListener,一旦因为网络问题导致Session失效,则自动丧失Controller身份,重新参与选举
· 收到Controller的请求,如果其epoch小于现在已知的controller_epoch,则直接拒绝

六、kafka的事务

七、kafka如何实现exactly-once

https://cloud.tencent.com/developer/article/1530090

1.幂等producer:保证发送单个分区的消息只会发送一次,不会出现重复消息

  1. PID与Sequence Number的引入实现了写操作的幂等性
    PID标记了Producer、topic、partition的唯一性,Seq标记了PID下每一个消息得唯一性。broker会记录已经收到得seq值,下一个seq一定是上一个seq+1,如果大于1,抛InvalidSequenceNumber异常(丢数据了),如果小于1,抛DuplicateSequenceNumber异常(数据重复了),生产端需要对这两种情况做处理
  2. 写操作的幂等性结合At Least Once语义实现了单一 Session 内的Exactly Once语义

2.事务(transaction):保证原子性地写入到多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚

Kafka 事务的本质是,将一组写操作(如果有)对应的消息与一组读操作(如果有)对应的 Offset 的更新进行同样的标记(即Transaction Marker)来实现事务中涉及的所有读写操作同时对外可见或同时对外不可见

3.流处理EOS:流处理本质上可看成是“读取-处理-写入”的管道。此EOS保证整个过程的操作是原子性。注意,这只适用于Kafka Streams

八、kafka不重复消费也不丢失数据

https://blog.csdn.net/xucong996/article/details/102511576?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

https://blog.csdn.net/qian_peng/article/details/115446162

1.消费者端

基础规则:每个消费者消费Topic分区的数据按照Offset进行消费
第一次消费:根据属性
auto.offset.reset:lastest/earliest
第二次消费开始:消费者在内存中记录上一次消费的offset + 1 = 这一次要消费的位置
Kafka将每个消费者消费的位置主动定期记录在一个Topic中:__consumer_offsets

2.生产者端

关闭自动提交offset
ack机制
ack = -1 kafka写入,副本同步完毕,同步的方式
ack=0 kafka不一定写入,异步的方式
ack=1 leader写入,但不等follower同步

九、如何解决kafka频繁rebalance

https://blog.csdn.net/qq_21383435/article/details/108720155

1.kafka rebalance是什么

rebalance指的是kafka的partition和消费组内的消费者成员数不匹配,出发的条件有以下三种:

  1. 消费组内成员增减;
  2. 同一topic下的partition数量变更
  3. 订阅的topic发生变化。 当消费者使用正则表达式订阅topic,而刚好又新建了对应的topic,也会触发rebalance

2.rebalance怎么解决

1.range分配 实现位置位于package org.apache.kafka.clients.consumer.RangeAssignor
2.roundRobin 分配 实现位置位于package org.apache.kafka.clients.consumer.RoundRobinAssignor
3.最新的kafka partiton分配策略 sticky 只挪动尽可能的分区来实现分配策略 实现位置位于package org.apache.kafka.clients.consumer.StickyAssignor

3.rebalance涉及的参数

在消费者启动时,某些参数可能会影响重平衡机制的发生,不当会导致重平衡,具体参数如下:

  1. session.timeout.ms 参考时间6s
    该参数是 Coordinator 检测消费者失败的时间,即在这段时间内客户端是否跟 Coordinator 保持心跳,如果该参数设置数值小,可以更早发现消费者崩溃的信息,从而更快地开启重平衡,避免消费滞后,但是这也会导致频繁重平衡,这要根据实际业务来衡量。

  2. max.poll.interval.ms 参考消费者处理消息最长耗时再加1min,默认是5分钟

消费者处理消息逻辑的最大时间,对于某些业务来说,处理消息可能需要很长时间,比如需要 1分钟,那么该参数就需要设置成大于 1分钟的值,否则就会被 Coordinator 剔除消息组然后重平衡。

  1. heartbeat.interval.ms 参考时间2s

该参数跟 session.timeout.ms 紧密关联,前面也说过,只要在 session.timeout.ms 时间内与 Coordinator 保持心跳,就不会被 Coordinator 剔除,那么心跳间隔的时间就是 session.timeout.ms,因此,该参数值必须小于 session.timeout.ms,以保持 session.timeout.ms 时间内有心跳。
在这里插入图片描述

4.避免rebalance

调整3中参数,避免kakfa出现误判消费者挂掉的情况

十、kafka的采用pull模式

https://www.cnblogs.com/yaohaitao/p/5777335.html

1.什么是pull模式

pull模式:consumer主动从brokers中拉取数据
push模式:brokers主动push数据给consumer 该模式下broker决定消息推送的速率,对于不同消费速度的consumer,会造成消费速度低的consumer崩溃

2.kafka采用pull模式

1.优势:下游consumer决定消息推送的速率;另外consumer可以自主决定是否批量的从broker拉取数据。
2.缺点:如果broker没有数据,consumer会处于不断轮询中,直到新消息到达。为了避免这点,Kafka有个参数可以让consumer阻塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发送)。

参考资料:
1.kafka高频面经:https://zhuanlan.zhihu.com/p/73475227

十一、kafka积压问题总结

https://cloud.tencent.com/developer/article/1839608

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一些 Kafka 高频面试题: 1. 什么是 KafkaKafka 是一个分布式流处理平台,主要用于处理实时数据流和实时数据流的存储。它使用发布/订阅模式,支持高吞吐量、持久性和容错性。 2. Kafka 的主要组件有哪些? Kafka 的主要组件包括生产者、消费者、Broker、主题、分区和副本。 3. Kafka 中的分区有什么作用? 分区是 Kafka 中的一个重要概念,它允许将主题分成多个部分,以便实现水平扩展和并行处理。每个分区都有一个唯一的标识符,称为分区 ID。 4. Kafka 的消息保证模式有哪些? Kafka 提供两种消息保证模式:at least once 和 exactly once。at least once 模式确保每条消息最少被传递一次,而 exactly once 模式确保每条消息恰好被传递一次。 5. Kafka 的消息保存策略有哪些? Kafka 的消息保存策略包括删除与保留。删除策略包括删除旧的消息和删除无用的主题,保留策略包括保留最近的消息和保留所有消息。 6. Kafka 的主题是如何分配到分区的? Kafka 使用一种称为哈希分区的算法,将主题中的消息均匀分配到分区中。该算法使用消息键和分区数来计算消息应该被分配到哪个分区中。 7. Kafka 中的消费者组是什么? 消费者组是一组消费者,用于消费同一主题的消息。Kafka 使用消费者组来实现负载平衡和故障转移。 8. Kafka 中的 ISR 是什么? ISR(In-Sync Replicas)是指与主副本同步的备份副本。当主副本失效时,ISR 中的任何一个备份副本都可以被提升为新的主副本。 9. Kafka 中的副本同步是如何实现的? Kafka 中的副本同步是通过使用复制管道来实现的。主副本将消息入其本地日志中,并将消息发送到其所有备份副本的复制管道中。备份副本将消息入其本地日志中,并在收到确认后将确认发送回主副本。 10. Kafka 中的消费者如何处理消息的重复? 在 at least once 模式下,消费者可能会收到重复的消息。为了避免重复处理,消费者可以使用消息的唯一标识符来检查消息是否已经被处理过。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值