9. Interview-Kafka

2020-07-21  本文已影响0人  allen锅

0 消息队列使用场景

1 消息中间件怎么保证消息幂等性/一致性?

2 Kafka架构

kafka架构 kafka架构

1)Producer :消息生产者,就是向kafka broker发消息的客户端;

2)Consumer :消息消费者,向kafka broker取消息的客户端;

3)Consumer Group (CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。

4)Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。

5)Topic :可以理解为一个队列,生产者和消费者面向的都是一个topic;

6)Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列;

7)Replica:副本,为保证集群中的某个节点发生故障时,该节点上的partition数据不丢失,且kafka仍然能够继续工作,kafka提供了副本机制,一个topic的每个分区都有若干个副本,一个leader和若干个follower。

8)leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader。

9)follower:每个分区多个副本中的“从”,实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个follower会成为新的follower。

3 零拷贝(Zero Copy)技术原理

4 Kafka中的ISR、OSR、AR又代表什么?

replica.lag.time.max.ms : 这个参数的含义是 Follower 副本能够落后 Leader 副本的最长时间间隔,当前默认值是 10 秒。

5 Kafka中的HW、LEO、LW、LSO等分别代表什么?

image.png

6 Kafka中是怎么体现消息顺序性的?怎么保证消息全局有序?

kafka怎么保证消息全局有序?

topic 只设置一个partition,这样所有的数据都往这一个partition发,能保证有序
但是对性能可就大打折扣了,一旦数据量提升,且有隐患。

下游消费者对topic做分组时间排序,性能也差。

采用特征数据处理
producer.send(new ProducerRecord<>(topic,messageNo,messageStr))
对这个 方法中的messageNo做文章。
messageNo = database.table.key
比如上面那条操作的key为 id = 100
messageNo = bigdata.ruozedata.100

计算partition
假设 hash(bigdata.ruozedata.100) = 99
99 % 3 = 0
数据分发到 p0 分区上
p0:insert u1 u2 u3 u4 delete
p1:
p2:

可能 bigdata.ruozedata.666 发送到了p1 分区上
p0:
p1: insert u1 u2 u3 u4 delete
p2:

这样就能保证对某一条数据的操作分发到单个partition中去,从而保证全局的有序性。

7 Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?

8 Kafka生产者客户端的整体结构是什么样子的?使用了几个线程来处理?分别是什么?

Producer架构 producer完整架构

整个生产者客户端由两个线程协调运行,这两个线程分别为主线程和 Sender 线程(发送线程)。在主线程中由 KafkaProducer 创建消息,然后通过可能的拦截器、序列化器和分区器的作用之后缓存到消息累加器(RecordAccumulator,也称为消息收集器)中。Sender 线程负责从 RecordAccumulator 中获取消息并将其发送到 Kafka 中。RecordAccumulator 主要用来缓存消息以便 Sender 线程可以批量发送,进而减少网络传输的资源消耗以提升性能。

9 “消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?如果正确,那么有没有什么hack的手段?

一般来说如果消费者过多,出现了消费者的个数大于分区个数的情况,就会有消费者分配不到任何分区。

开发者可以继承AbstractPartitionAssignor实现自定义消费策略,从而实现同一消费组内的任意消费者都可以消费订阅主题的所有分区。

10 消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?

在旧消费者客户端中,消费位移是存储在 ZooKeeper 中的。而在新消费者客户端中,消费位移存储在 Kafka 内部的主题__consumer_offsets 中。当前消费者需要提交的消费位移是offset+1。

11 有哪些情形会造成重复消费?

11 哪些情景会造成消息漏消费?

12 当你使用 kafka-topics.sh 创建(删除)了一个 topic 之后,Kafka 背后会执行什么逻辑?

13 topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么?

可以增加,当分区数增加时,就会触发订阅该主题的所有 Group 开启 Rebalance。首先,Rebalance过程中,所有 Consumer 实例都会停止消费,等待 Rebalance 完成。然后所有 Consumer 实例共同参与,全部重新分配所有分区。其实更高效的做法是尽量减少分配方案的变动。

bin/kafka-topics.sh --zookeeper localhost:2181/kafka --alter --topic topic-config --partitions 3

14 topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么?

不支持,因为删除的分区中的消息不好处理。如果直接存储到现有分区的尾部,消息的时间戳就不会递增,如此对于 Spark、Flink 这类需要消息时间戳(事件时间)的组件将会受到影响;如果分散插入现有的分区,那么在消息量很大的时候,内部的数据复制会占用很大的资源,而且在复制期间,此主题的可用性又如何得到保障?与此同时,顺序性问题、事务性问题,以及分区和副本的状态机切换问题都是不得不面对的。

15 Kafka有内部的topic吗?如果有是什么?有什么所用?

__consumer_offsets,保存消费者offset

16 kafka分区分配策略

kafka中每个主题一般都会有很多个分区,为了及时消费到数据,我们可能会启动很多个消费者去一个消费topic中的数据。每个分区只能由消费组内的一个消费者去消费。那么,同一个消费组内的消费者是如何确定消费哪些分区的数据呢?

kafka内部中存在两种分配策略:Range和RoundRobin。

kafka分配分区的条件:1)同一个消费组内消费者的新增、关闭或崩溃,2)订阅的主题新增分区。

是对每个主题而言的。首先按照分区序号排序,然后将消费者排序。分区数/消费者数=m,如果m!=0,前m个消费者多消费一个分区(每个主题)

使用RoundRobin策略有两个前提条件必须满足:1)同一个Consumer Group里面的所有消费者的num.streams必须相等;2)每个消费者订阅的主题必须相同。

所以这里假设前面提到的2个消费者的num.streams = 2。RoundRobin策略的工作原理:将所有主题的分区组成 TopicAndPartition 列表,然后对 TopicAndPartition 列表按照 hashCode 进行排序,分发给每一个消费者。(其实就是按分区名hash排序后平均分配给每一个消费者的线程)

总结:目前我们还不能自定义分区分配策略,只能通过partition.assignment.strategy参数选择 range 或 roundrobin。partition.assignment.strategy参数默认的值是range。

17 简述Kafka的日志目录结构?

每个分区对应一个文件夹,文件夹的命名为topic-0,topic-1,内部为.log和.index文件。

生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据定位效率低下,Kafka 采取了分片和索引机制,将每个 partition 分为多个 segment。每个 segment对应两个文件——“.index”文件和“.log”文件。这些文件位于一个文件夹下,该文件夹的命名规则为:topic 名称+分区序号。例如,first 这个 topic 有三个分区,则其对应的文件夹为 first-0,first-1,first-2。index 和 log 文件以当前 segment 的第一条消息的 offset 命名。下图为 index 文件和 log 文件的结构示意图。其中 “.index”文件存储大量的索引信息,“.log”文件存储大量的数据,索引文件中的元 数据指向对应数据文件中 message 的物理偏移地址。

.index和.log关系

18 Kafka Controller 的作用?

它负责管理整个集群中所有分区和副本的状态。当某个分区的leader副本出现故障时,由controller负责为该分区选举新的leader副本。当检测到某个分区的ISR集合发生变化时,由controller负责通知所有broker更新其元数据信息。当使用kafka-topics.sh脚本为某个topic增加分区数量时,同样还是由控制器负责分区的重新分配。

19 Kafka中有那些地方需要选举?这些地方的选举策略又有哪些?

20 失效副本是指什么?有那些应对措施?

osr中的副本,如果与leader通信后,会尝试与leader同步,同步的策略是首先将当前记录的hw之后的消息删除,然后与leader同步,当与leader基本同步之后(存储的消息的offset大于当前isr中的hw),就重新回到isr之中。

21 Kafka的那些设计让它有如此高的性能?

22 如果我指定了一个offset,Kafka Controller怎么查找到对应的消息?

例如,读取offset=368776的Message,需要通过如下两个步骤。

00000000000000000000.index表示最开始的文件,其实偏移量(offset)为0;第二个文件00000000000000368769.index的其实偏移量为368770(368769+1),依次类推。以其实偏移量命名并排序这些文件,只要根据offset二分查找文件列表,就可以快速定位到具体文件。

当offset=368776时,定位到00000000000000368769.index|log。

通过第一步定位到Segment File,当offset=368776时,依次定位到00000000000000368769.index的元数据物理位置和00000000000000368769.log的物理偏移地址,然后再通过00000000000000368769.log顺序查找,知道offset=368776为止。

Segment Index File采取稀疏索引存储方式,可以减少索引文件大小,通过Linux mmap接口可以直接进行内存操作。稀疏索引为数据文件的每个对应Message设置一个元数据指针,它比稠密索引节省了更多的存储空间,但查找起来需要消耗更多的时间。

23 如果我指定了一个timestamp,Kafka怎么查找到对应的消息?

原理同上 但是时间的因为消息体中不带有时间戳 所以不精确

24 kafka的选举机制

25 KafkaConsumer是非线程安全的,那么怎么样实现多线程消费?

image.png

26 简述消费者与消费组之间的关系?

27 创建topic时如何选择合适的分区数?

根据集群的机器数量和需要的吞吐量来决定适合的分区数.

在 Kafka 中,性能与分区数有着必然的关系,在设定分区数时一般也需要考虑性能的因素。对不同的硬件而言,其对应的性能也会不太一样。
可以使用Kafka 本身提供的用于生产者性能测试的 kafka-producer- perf-test.sh 和用于消费者性能测试的 kafka-consumer-perf-test.sh来进行测试。
增加合适的分区数可以在一定程度上提升整体吞吐量,但超过对应的阈值之后吞吐量不升反降。如果应用对吞吐量有一定程度上的要求,则建议在投入生产环境之前对同款硬件资源做一个完备的吞吐量相关的测试,以找到合适的分区数阈值区间。
分区数的多少还会影响系统的可用性。如果分区数非常多,如果集群中的某个 broker 节点宕机,那么就会有大量的分区需要同时进行 leader 角色切换,这个切换的过程会耗费一笔可观的时间,并且在这个时间窗口内这些分区也会变得不可用。
分区数越多也会让 Kafka 的正常启动和关闭的耗时变得越长,与此同时,主题的分区数越多不仅会增加日志清理的耗时,而且在被删除时也会耗费更多的时间。

28 优先副本是什么?它有什么特殊的作用?

优先副本 会是默认的leader副本 发生leader变化时重选举会优先选择优先副本作为leader

29 Kafka有哪几处地方有分区分配的概念?简述大致的过程及原理

创建主题时
如果不手动指定分配方式 有两种分配方式

消费组内分配

30 聊一聊你对Kafka的Log Retention的理解?

kafka留存策略包括 删除和压缩两种
删除: 根据时间和大小两个方式进行删除 大小是整个partition日志文件的大小
超过的会从老到新依次删除 时间指日志文件中的最大时间戳而非文件的最后修改时间
压缩: 相同key的value只保存一个 压缩过的是clean 未压缩的dirty 压缩之后的偏移量不连续 未压缩时连续

31 聊一聊你对Kafka的Log Compaction的理解?

32 Kafka的旧版Scala的消费者客户端的设计有什么缺陷?

老版本的 Consumer Group 把位移保存在 ZooKeeper 中。Apache ZooKeeper 是一个分布式的协调服务框架,Kafka 重度依赖它实现各种各样的协调管理。将位移保存在 ZooKeeper 外部系统的做法,最显而易见的好处就是减少了 Kafka Broker 端的状态保存开销。

ZooKeeper 这类元框架其实并不适合进行频繁的写更新,而 Consumer Group 的位移更新却是一个非常频繁的操作。这种大吞吐量的写操作会极大地拖慢 ZooKeeper 集群的性能。

33 聊一聊你对Kafka底层存储的理解(页缓存、内核层、块层、设备层)

34 聊一聊Kafka的延时操作的原理

35 聊一聊Kafka控制器的作用

36 消费再均衡的原理是什么?(提示:消费者协调器和消费组协调器)

37 Kafka中的幂等是怎么实现的?

38 Kafka中的事务是怎么实现的?

39 Kafka中有那些地方需要选举?这些地方的选举策略又有哪些?

40 失效副本是指什么?有那些应对措施?

41 多副本下,各个副本中的HW和LEO的演变过程

42 为什么Kafka不支持读写分离?

43 Kafka在可靠性方面做了哪些改进?(HW, LeaderEpoch)

44 Kafka中怎么实现死信队列和重试队列?

45 Kafka中的延迟队列怎么实现

46 Kafka中怎么做消息审计?

47 Kafka中怎么做消息轨迹?

48 Kafka中有那些配置参数比较有意思?聊一聊你的看法

49 Kafka中有那些命名比较有意思?聊一聊你的看法

50 Kafka有哪些指标需要着重关注?

51 怎么计算Lag?(注意read_uncommitted和read_committed状态下的不同)

52 Kafka有什么优缺点?

参考58和59

53 还用过什么同质类的其它产品,与Kafka相比有什么优缺点?

参考59

54 为什么选择Kafka?

参考58和59

55 在使用Kafka的过程中遇到过什么困难?怎么解决的?

消费者使用过程中一定要注意不能阻塞poll方法逻辑,一旦阻塞很造成消费业务的不健康现象。
• 问题一
现象:消费到消息后去进行消费进度提交时提交失败。
可能原因:消费消息和处理消息同步进行,整体流程为“消费->处理->提交”。其中处理过程耗时过久,导致消费者和服务端超时断开,此时进行消费提交会报失败,默认超时时间为5分钟。

• 问题二
现象:多消费者并发消费,但是消费速度极慢,导致消费堆积。从服务端日志可以看到大量的消费组rebalance相关的日志。
可能原因:消费逻辑与问题一相同,需要注意的是消费者在poll方法被阻塞时无法对服务端请求做出回应。消费者断开后执行重连,从而使消费组进入Rebalancing状态并通知所有相关消费者,此时若存在消费者阻塞,无法及时响应,则会导致Rebalance动作无法及时完成,此过程中所有消费者都无法消费。

优化建议:优化处理逻辑,快速处理数据;消费和处理进行解耦,使用不同的线程处理;创建消费者时适当减小max.poll.records的配置,默认为500,减少单次消息处理时间。

56 怎么样才能确保Kafka极大程度上的可靠性?

57 聊一聊你对Kafka生态的理解

58 Kafka跟RocketMQ吞吐量如何?其他方面呢?

59 消息吞吐量为什么Kafka>rocketmq>rabbitmq?rocketmq哪些方面导致吞吐量比Kafka小?

60 kafka跟rabbitmq区别?

kafka&rabbitmq

61 Kafka跟MQ对比?

62 kafka使用建议

生产消息:
• 生产消息消息发送失败需要有重试机制。建议重试3次,通过参数:retries=3 配置。
• 生产的callback函数不能阻塞,否则会阻塞客户端消息的发送对于时延敏感消息,设置发送优化:linger.ms=0。

消费消息:
• 使用长连接pull模式消费消息,不要消费结束就关闭consumer通道,这样会导致频繁rebalance,阻塞消费。
• consumer需周期性poll(建议间隔为200毫秒),维持和server端的心跳,避免因为心跳超时导致consumer频繁加入和退出,阻塞消费。
• consumer拉去消息的逻辑poll方法不能有阻塞。
• consumer数量不能超过topic的分区数,否则会有consumer拉取不到消息。
• 确保处理完消息后再做消息commit,避免业务消息处理失败,无法重新拉取处理失败的消息。
• Kafka不能保证消费重复的消息,业务侧需保证消息处理的幂等性。

63 kafka之mmap文件读写方式

上一篇 下一篇

猜你喜欢

热点阅读