全网最全最通俗最装b的Kafka面试题

前言

Kafka面试题网上有很多,但我看了很多之后发现大部分的面试题要么不全,要么不深入,要么就是没顺序,要么就是说的让人根本看不懂,看了也不知道面试怎么去表达。
所以参考了很多资料后,励志呕心沥血决定写一份全网最全最通俗最装b的Kafka面试题,让你看了能跟面试官去吹个几天几夜。
因为Kafka内容过多,所以我会持续更新的,如果你有看不懂的或者有我没写到而且搞不懂的面试题,欢迎积极留言!


Kafka是什么

Kafka是一款分布式流处理框架,用于实时构建流处理应用 。

两大应用场景:

  1. 消息队列。
  2. 数据处理。

Kafka组成部分

  1. broker:Kafka服务器,负责存储和转发
  2. topic:消息类别
  3. partition:分区,一个topic分为若干partition分区,消息就存在partition中。可以理解为topic是一块大蛋糕,不能只装在一个盘子里(效率低),切成若干块然后放在不同的盘子里(partition)
  4. producer:生产者
  5. consumer:消费者
  6. consumer group:消费者组,一个消费者组由若干消费者组成。
  7. zookeeper:保存着集群 broker、 topic、 partition等meta 数据;另外,还负责broker故障发现, partition leader选举,负载均衡等功能

consumer采用pull(拉)还是push(推)

采用了pull,也就是消费者从broker拉取消息,因为这样消费者可以根据自己的消费能力去消费。吃饭吃的快慢由你自己控制。

假设是push的话,也就是broker给消费者推送消息,那么推送快了,消费者可能会崩溃,推送慢了,会降低效率。

多副本机制

Kafka每个partition可以拥有多个副本,一个为leader,其余的为follower。leader提供读写服务,而follower从leader里拉取数据进行同步,当leader宕机后,follower可以应聘成为leader。

可以通俗的理解为,follower就是个备胎,平时没用,只有leader挂了之后才发挥作用。

装逼加分项

​ Kafka2.4以前只能由leader进行读写,2.4开始,follower可以提供有限的读。比如当leader副本不在我这个机房时,那么我需要跨数据中心去获取数据,会耗费很多成本,所以2.4开始支持向附近的follower副本进行读取数据,来减小成本。

AR、ISR、OSR是什么

AR=ISR+OR

某一个分区的所有副本称为AR。

follower副本需要从leader拉取数据,如果超过一定时间(默认10秒)没有和leader同步,就会认为它滞后太多,放到OSR集合。没超过10秒的就在ISR里。

通俗理解,ISR就是优等生,OSR就是差生,AR就是所有同学。

ack有几种

ack表示的是生产者生产消息时,写入副本的严格程度。

有三种,0, 1, -1

0:生产者发出消息就不管了。性能最高,但可靠性最低,因为服务器挂了消息就没了。

1:默认值。leader成功接受后就不管了,也就是不管follower有没有同步。性能和可靠性都中等。这种情况leader挂了消息就没了。

-1:all。ISR中所有follower都接受后才算成功。性能最低,但可靠性最高。

LEO、HW是什么

LEO:每个副本下一个待写入消息的offset。比如现在写完了0-10,那么LEO就是11。

HW:所有副本中最小的LEO值。消费者拉取消息时,只能拉取到HW之前的值。

HW有什么用

为了避免消息丢失。

比如:leader现在offset写到了10,但是follower还没来得及同步,假设follower同步到了5。如果没有HW的话,此时消费者去拉取leader的6-10号消息,消费的过程中,leader挂掉了,然后某个follower成为了新的leader,然后生产者向这个新的leader写入消息,因为这个新的leader的offset写到了5,所以从6开始写,假设写到了10,也就是6-10是新消息。此时,消费者消费完了之前的消息,然后提交了offset,那么下一次再消费就会从11开始消费,此时新的leader刚刚写入的6-10号新消息就平白无故丢失掉了。

所以丢失的消息是:新的leader上任后,到消费者提交offset,这一段时间生产的消息会丢失。

那么有了HW的话,像刚刚那种情况,HW是所有副本最小的LEO,所以消费者最多消费到5号消息,不能消费原来leader的6-10号消息。那么即使leader挂掉,然后选了新的leader并生产新消息,消费者提交的offset也只是消费完了5,下一次可以从6开始消费,就不会丢失消息了。

副本同步过程

注意一下:每个副本都有各自的LEO和HW,除此之外,leader所在的broker还保存了所有follower的LEO值,被称为远程副本,用来帮助leader更新HW值。

过程:

  1. leader收到生产者的新消息,更新自身LEO,并从更新HW(从远程副本中选最小的LEO)

  2. follower向leader拉取,发请求时带上自身的LEO发给leader。

  3. leader收到follower的请求后,拿follower发来的LEO值更新远程副本,然后更新HW,然后把数据发给follower,发数据的同时带上HW。

  4. follower收到数据后,更新自身LEO,然后根据leader发来的HW,和自身LEO比较,选最小的更新为HW。

    此时leader和follower都更新完了LEO,但HW都没变,所以HW需要下一次请求时改变。其实就是重复2~4的步骤,然后HW值就会改变,那么我就复制粘贴一下吧。

  5. (步骤2)follower向leader拉取,发请求时带上自身的LEO发给leader。

  6. (步骤3)leader收到follower的请求后,拿follower发来的LEO值更新远程副本,然后更新HW,然后把数据发给follower,发数据的同时带上HW。

  7. (步骤4)follower收到数据后,更新自身LEO,然后根据leader发来的HW,和自身LEO比较,选最小的更新为HW。

装逼加分项

上述步骤存在的问题:我们发现follower的HW更新总是慢于leader,存在一定延迟,所以当leader连续变更时,会出现数据丢失和数据不一致的问题。

  1. 数据丢失:假设leader的LEO和HW都是2,follower的LEO为2,HW为1(还没来得及更新)。

    • follower重启,重启后进行日志截断,LEO要更新为HW的值,所以follower的2号数据就没了。但leader还有这条数据对吧?
    • leader宕机了,那么follower就成了新的leader。旧的leader重启后,进行日志截断,HW不能超过新的leader,所以HW也变为了1,那么2号数据就彻底丢失了。
  2. 数据不一致:假设leader的LEO和HW都是2,follower的LEO和HW都是1。

    • 某时刻,leader和follower都宕机了,然后follower先重启成功了,那么理所当然成为了新的leader。
    • 新的leader(LEO和HW都为1)接收到了生产者的消息,然后LEO和HW更新为2。
    • 此时旧的leader也重启成功了,进行日志截断,发现自己的HW是2,新的leader的HW也是2,那么就不截断了。此时,就出现了数据不一致的情况,旧的leader的2号数据是宕机前的数据,但新的leader的2号数据是重启后新的数据。

怎么解决?leader epoch闪亮登场。

leader epoch,领导者时代,简单理解为一个键值对<epoch, offset>,epoch表示哪个时代,单调递增,offset表示这个时代从哪个offset开始。

比如<0,0> 表示0号时代的offset从0开始, <1,100>表示1号时代的offset从100开始。

每出现一个新的leader,都会生成一个新的时代。那么在需要进行日志截断时,就不用根据HW来判断了,而是通过leader epoch。

具体过程:

  1. 数据丢失如何解决:沿用之前的例子。假设leader的LEO和HW都是2,follower的LEO为2,HW为1(还没来得及更新)。
    • follower重启,向leader发送leader epoch请求,请求告诉自己现在是哪个时代。因为二人处于同一时代,所以leader将自己的LEO发送给follower,follower发现leader的LEO和自己的一样,那么就不进行截断了。
    • leader宕机后,follower成为了新的leader,所以开辟了一个新的时代,leader epoch为<1,2>,也就是新的时代offset从2开始。旧的leader重启后,向新的leader发送leader epoch请求,请求告诉自己现在是哪个时代。它知道自己现在处于1号时代,offset从2开始,所以消息就不会丢失了。
  2. 数据不一致如何解决:沿用之前的例子。假设leader的LEO和HW都是2,follower的LEO和HW都是1。
    • 某时刻,leader和follower都宕机了,然后follower先重启成功了,那么理所当然成为了新的leader。
    • 新的leader开辟一个新的时代,<1,1>。此时新的leader(LEO和HW都为1)接收到了生产者的消息。LEO改为2。
    • 此时旧的leader也重启成功了,发送请求,请求告诉自己现在是哪个时代,发现时代不一样,所以旧的leader根据新leader的leader epoch进行截断,<1,1>表示offset从1开始,所以旧的leader的老数据就被截断了,解决了数据不一致。

offset(位移)是什么

每个分区中,每条消息都有一个唯一性的ID,用来标识它在分区中的位置,这个就是offset。我们可以通过offset来记录我们消费到了哪里。
在Kafka0.9以前,offset是保存在了zookeeper,但是如果保存在zookeeper的话,消费者需要和zookeeper频繁的交互,所以很影响性能,所以在zookeeper0.9以后,offset保存在了broker中一个默认的topic中,叫_consumer_offsets。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值