一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

Kafka 面试题(2022最新版)

🐶 程序猿周周
⌨️ 短视频小厂BUG攻城狮
🤺 如果文章对你有帮助,记得关注、点赞、收藏,一键三连哦,你的支持将成为我最大的动力


本文是 Java 面试总结系列的第1️⃣5️⃣篇文章,该专栏将整理和梳理笔者作为 Java 后端程序猿在日常工作以及面试中遇到的实际问题,通过这些问题的系统学习,也帮助笔者顺利拿到阿里、字节、华为、快手等Offer,也祝愿大家能够早日斩获自己心仪的Offer。由于笔者能力有限,若有错误或疏忽还望各位大佬们不吝指出…

序号 地址
1 MySQL数据库面试题总结(2022版)
2 Redis面试题总结(2022版)
3 计算机网络面试题总结(2022版)
4 操作系统面试题总结(2022版)
5 Linux面试题总结(2022版)
6 Spring面试题总结(2022版)
7 Java基础面试题总结(2022版)
8 Java集合面试题总结(2022版)
9 Java并发面试题总结(2022版)
10 Java虚拟机面试题总结(2022版)
11 Java异常面试题总结(2022版)
12 设计模式面试题总结(2022版)
13 Dubbo面试题总结(2022版)
14 Netty面试题总结(2022版)
15 Kafka面试题总结(2022版)

1 基础

1、什么是kafka?

Kafka 是分布式发布-订阅消息系统,它最初是由 LinkedIn 公司开发的,之后成为 Apache 项目的一部分,Kafka是一个分布式,可划分的,冗余备份的持久性的日志服务,它主要用于处理流式数据。

2、为什么要用kafka?

可以理解成为什么要使用消息队列

  • 缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理。

  • 解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。

  • 冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅topic的服务消费到,供多个毫无关联的业务使用。

  • 健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正常进行。

  • 异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

3、Kafka使用场景?

  • 日志收集:一个公司可以用 Kafka 可以收集各种服务的 log,通过 Kafka 以统一接口服务的方式开放给各种 consumer,如 Hadoop、HBase、Solr等。

  • 消息系统:解耦和生产者和消费者、缓存消息等。

  • 用户行为跟踪:Kafka 经常被用来记录web用户或者 app 用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到 kafka 的 Topic 中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到 Hadoop、数据仓库中做离线分析和挖掘。

  • 运营指标:Kafka 也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。

  • 流式处理:如 Spark streamin 和 Flink。

4、讲讲 Kafka 的架构?

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

先来了解一下 Kafka 架构中一些专有名词概念:

  • Producer(生产者):也就是发送消息的一方。生产者负责创建消息,然后将其发送到 Kafka。

  • Consumer(消费者):也就是接受消息的一方。消费者连接到 Kafka 并接收消息,进而进行相应的业务逻辑处理。

  • Consumer Group(消费组): 一个消费者组可以包含一个或多个消费者。使用多分区+多消费者方式可以极大提高数据下游的处理速度。 同一消费组中的消费者不会重复消费消息,同样的,不同消费组中的消费者消息消息时互不影响。Kafka 就是通过消费组的方式来实现消息 P2P 模式和广播模式。

  • Broker:服务代理节点。Broker 是 Kafka 的服务节点,即 Kafka 的服务器。

  • Topic:可以理解为一个队列,一个 Topic 又分为一个或多个分区。

  • Partition(分区):Topic 是一个逻辑的概念,它可以细分为多个分区,每个分区只属于单个主题。 同一个主题下不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志(Log)文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(Offset)。

  • Offset:是消息在分区中的唯一标识,Kafka 通过它来保证消息在分区内的顺序性,不过 Offset 并不跨越分区,也就是说,Kafka 保证的是分区有序性而不是主题有序性,即局部有序。

  • Replication(副本):是 Kafka 保证数据高可用的方式,Kafka 同一 Partition 的数据可以在多 Broker 上存在多个副本,通常只有主副本对外提供读写服务,当主副本所在 Broker 崩溃或发生网络一场,Kafka 会在 Controller 的管理下会重新选择新的 Leader 副本对外提供读写服务。

  • Record:实际写入 Kafka 中并可以被读取的消息记录。每个 Record 包含了 key、value 和 timestamp。

5、Kafka 分区的目的?

分区对于 Kafka 集群的好处是:实现负载均衡。分区对于消费者来说,可以提高并发度,提高效率。

6、Kafka 如何实现消息有序性?

kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在里面保证消息的顺序性。但是分区之间的消息是不保证有序的。

7、Kafka 中 ISR、AR 代表什么?

  • ISR(In-Sync Replicas) 副本同步队列
  • AR(Assigned Replicas) 所有副本

leader 会动态维护一个与其基本保持同步的 Replica 列表,该列表即为 ISR,每个 Partition 都会有一个 ISR,当 follower 从 leader 同步数据有一些延迟(包括延迟时间 replica.lag.time.max.ms 和延迟条数 replica.lag.max.messages 两个维度),任意一个超过阈值都会把 follower 剔除出 ISR, 存入 OSR(Outof-Sync Replicas) 列表,新加入的 follower 也会先存放在 OSR 中。而 AR = ISR + OSR。

8、Kafka 为什么这么快?

  • Cache Filesystem Cache PageCache 缓存。

  • 顺序写:由于现代的操作系统提供了预读和写技术,磁盘的顺序写大多数情况下比随机写内存还要快。

  • Zero-copy:零拷技术减少数据拷贝次数。

  • Batching of Messages(批量量处理):合并小的请求,然后以流的方式进行交互,直顶网络上限。

  • Pull(拉模式):使用拉模式进行消息的获取消费,与消费端处理能力相符。

9、Producer 如何优化写速度?

  • 增加线程。
  • 提高 batch.size。
  • 增加更多 producer 实例。
  • 增加 partition 数。
  • 设置 acks=-1 时,如果延迟增大,可以增大 num.replica.fetchers(follower 同步数据的线程数)来调解。
  • 跨数据中心的传输:增加 socket 缓冲区设置以及 OS tcp 缓冲区设置。

10、Kafka 在 Zookeeper 中的结构?

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

2 Producer

1、Producer 写入消息的方式?

Kafka 的 Producer 采用 push 模式将消息发布到 broker,每条消息都被 append 到 Partition 中,属于顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障 Kafka 吞吐率)。

2、写入消息时的路由策略?

Producer 发送消息到 broker 时,会根据分区算法选择将其存储到哪一个 Partition。其路由机制为:

1)指定了 Partition,则直接使用;

2)未指定 Partition 但指定 key,通过对 key 的 value 进行 hash 选出一个 Partition;

3)Partition 和 key 均未指定,就使用轮询选出一个 Partition。

3、写入消息的流程?

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

1)Producer 先从 Zookeeper 的 /brokers/.../state 节点找到该 Partition 的 Leader;

2)Producer 将消息发送给该 Leader;

3)Leader 将消息写入本地 log;

4)Followers 从 Leader pull 消息,写入本地 log 后向 Leader 发送 ACK;

5)Leader 收到 ISR 中所有 replica 的 ACK 后,增加 HW(high watermark,最后 commit 的 offset)并向 Producer 发送 ACK。

4、Kafka 的 ACK 机制?

Kafka 生产者 ProducerConfig 中的 ACK 配置一般常设置三种值:

  • 1(默认)

消息发送到 Kafka 后,经过 Leader 成功接收消息的的确认,就算是发送成功了。在这种情况下,如果当 Follower 尚未同步数据时刚好 Leader 宕机则会导致数据丢失。

  • 0

生产者将数据发送出去就不管了,不去等待任何返回。这种情况下数据传输效率最高,但是数据可靠性也是最低的。

  • -1

生产者需要等待 ISR 中的所有 Follower 都确认接收到数据后才算一次发送完成,可靠性最高。当 ISR 中所有 Replica 都向 Leader 发送 ACK 时,Leader 才 commit,这时候 Producer 才能认为一个请求中的消息都 commit 了。

当然,如果 Leader 接受数据候在 Follower 尚未同步数据时宕机,那么 Producer 会感知消息未发送成功并重试。

ACK = -1 能否可以代表消息一定不丢失?

当然不能,如果 Partition 只有一个副本,也就是只有一个 Leader,没有其他 Follower,那么即使它已经完成接受消息,但是接受消息过后宕机了,一样会导致数据丢失。

5、说说 Delivery Guarantee?

Kafka 消息有以下三种可能的 delivery guarantee:

  • At most once:消息可能会丢,但绝不会重复传输;
  • At least one:消息绝不会丢,但可能会重复传输;
  • Exactly once:每条消息肯定会被传输一次且仅传输一次,很多时候这是用户所想要的。

Producer 到 Broker 的 delivery guarantee semantic 非常直接。当producer向broker发送消息时,一旦这条消息被commit,由于replication的存在,它就不会丢。但是如果producer发送数据给broker后,遇到的网络问题而造成通信中断,那producer就无法判断该条消息是否已经commit。这一点有点像向一个自动生成primary key的数据库表中插入数据。虽然Kafka无法确定网络故障期间发生了什么,但是producer可以生成一种类似于primary key的东西,发生故障时幂等性的retry多次,这样就做到了Exactly one。所以目前默认情况下一条消息从producer和broker是确保了At least once,但可通过设置producer异步发送实现At most once。

3 Broker

1、Broker 如何存储消息?

物理上把 Topic 分成一个或多个 Partition(对应 server.properties 中的 num.partitions=3 配置),每个 Partition 物理上对应一个文件夹(该文件夹存储该 Partition 的所有消息和索引文件)。如:

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

2、Broker 删除消息策略?

无论消息是否被消费,Kafka 都会保留所有消息。有两种策略可以删除旧数据:

  • 基于时间:log.retention.hours=168

  • 基于大小:log.retention.bytes=1073741824

需要注意的是,因为 Kafka 读取特定消息的时间复杂度为 O(1),即与文件大小无关,所以这里删除过期文件与提高 Kafka 性能无关

3、Topic 的创建流程?

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

1)Controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher,当 Topic 被创建时,则 Controller 会通过 watch 得到该 Topic 的 Partition 和 Replica 的分配信息。

2)Controller 从 /brokers/ids 读取当前所有可用的 Broker 列表,对于 set_p 中的每一个 Partition:

2.1)从分配给该 Partition 的所有 Replica(称为 AR)中任选一个可用的 Broker 作为新的 Leader,并将 AR 设置为新的 ISR;

2.2)将新的 Leader 和 ISR 写入 /brokers/topics/[topic]/partitions/[partition]/state

3)Controller 通过 RPC 向相关的 Broker 发送 LeaderAndISRRequest。

4、Topic 删除流程?

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

相比如创建,删除就较为简单很多:

1)Controller 在 ZooKeeper 的 /brokers/topics 节点上注册 watcher,当 Topic 被删除,则 Controller 会通过 watch 得到该 Topic 的 Partition 和 Replica 的分配信息。

2)若 delete.topic.enable=false 直接结束;否则 Controller 注册在 /admin/delete_topics 上的 watch 被 fire,Controller 通过回调向对应的 Broker 发送 StopReplicaRequest。

4 Consumer

1、Kafka 的消费模式?

消息队列中消息的消费模型通常有两种:推送模型(push)和拉取模型(pull)。

  • 推送模型(push)

基于推送模型的消息队列,由消息代理记录消费者的消费状态,但这种方式往往无法很好地保证消息被处理。同时这种模式还有一个明显缺点,就是消息被标记为消费后,其它消费者则不可以再消费。

  • 拉取模型(pull)

Kafka 采用拉取(pull)模型,由消费者自己记录消费状态,每个消费者互相独立地顺序读取每个分区的消息。消费者拉取的最大上限通过最高水位(watermark)控制,生产者最新写入的消息如果还没有达到备份数量,对消费者是不可见的。

这种由消费者控制偏移量的优点是:消费者可以按照任意的顺序消费消息。比如,消费者可以重置到旧的偏移量,重新处理之前已经消费过的消息;或者直接跳到最近的位置,从当前的时刻开始消费。

一文整理常见Java后端面试题系列——Kafka篇(2022最新版)

在一些消息系统中,消息代理会在消息被消费之后立即删除消息。如果有不同类型的消费者订阅同一个主题,消息代理可能需要冗余地存储同一消息;或者等所有消费者都消费完才删除,这就需要消息代理跟踪每个消费者的消费状态,这种设计很大程度上限制了消息系统的整体吞吐量和处理延迟。Kafka 的做法是生产者发布的所有消息会一致保存在 Kafka 集群中,不管消息有没有被消费。用户可以通过设置保留时间来清理过期的数据,比如,设置保留策略为两天。那么,在消息发布之后,它可以被不同的消费者消费,在两天之后,过期的消息就会自动清理掉。

2、Consumer 的两套 API?

kafka 给我们提供了两套 Consumer API,分别是 The high-level Consumer API 和 The SimpleConsumer API。(其中 High-level Consumer API 提供了一个从 Kafka 消费数据的高层抽象,而 SimpleConsumer API 则需要开发人员更多地关注细节。)

  • The high-level Consumer API

High-level Consumer API 提供了 Consumer Group 的语义,一个消息只能被 Group 内的一个 Consumer 所消费,且 Consumer 消费消息时不关注 offset,最后一个 offset 由 Zookeeper 保存。

同时 High-level consumer API 还支持多线程消费,但需要注意:

1)如果消费线程大于 Partition 数量,则有些线程将收不到消息。

2)如果 Partition 数量大于线程数,则有些线程多收到多个 Partition 的消息。

3)如果一个线程消费多个Partition,则无法保证接收消息的顺序,只能保证 Partition 内部有序。

  • The SimpleConsumer API

使用 The SimpleConsumer API,你可以对 Partition 有更多的控制权,如多次消费一个消息,只消费 Partition 中部分消息等。

但是使用此 API 时,Partition、Offset、Broker、Leader 等不再透明,需要业务去处理:

1)必须在应用程序中跟踪 Offset,从而确定下一条应该消费哪条消息。

2)应用程序需要通过程序获知每个 Partition 的 Leader,同时还需要处理 Leader 的变更。

3、Consumer Delivery Guarantee?

如果将 Consumer 设置为 autocommit,Consumer 一旦读到数据立即自动 commit,但此处只考虑到了读取消息的过程,那 Kafka 确保了 Exactly once。但实际使用中 Consumer 还要对读取到的消息做进一步处理:

  • 收到消息先提交再处理

这种模式下,如果 consumer 在 commit 后还没来得及处理消息就 crash 了,下次重新开始工作后就无法读到刚刚已提交而未处理的消息,这就对应于 At most once

  • 收到消息先处理再提交

这种模式下,如果在处理完消息之后 commit 之前 consumer crash 了,下次重新开始工作时还会处理刚刚未 commit 的消息,实际上该消息已经被处理过了。这就对应于 At least once。

  • 实现 Exactly once

精典的做法是引入两阶段提交。除此以外如果能让 offset 和操作输入存在同一个地方,会更简洁和通用,且这种方式可能更好,因为许多输出系统可能不支持两阶段提交。

5 集群

1、如何实现高可用?

同一个 Partition 可能会有多个 Replica(对应 server.properties 配置中的 default.replication.factor=N)。没有 Replica 的情况下,一旦 Broker 宕机,其上所有 Partition 的数据都不可被消费,同时 Producer 也不能再将数据存于其上的 Partition。

引入 Replica 之后,同一个 Partition 可能会有多个 Replica,而这时需要在这些 Replica 之间选出一个 Leader,Producer 和 Consumer 只与这个 Leader 交互,其它 Replica 作为 Follower 从 Leader 中复制数据。

2、如何分配 Replica?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4XkZw5f1-1647962263984)(https://gitee.com/zhouas666/imgur/raw/master/img/qrcode_for_gh_6bda378a94f7_344.jpg)]

相关文章

暂无评论

暂无评论...