kafka常见面试题

4 篇文章 0 订阅
2 篇文章 0 订阅

kafka

1、kafka名词解释和工作

  1. producer:消息生产者,就是向kafka broker发消息的客户端。
  2. consumer:消息消费者,向kafka broker取消息的客户端。
  3. topic:可以理解为一个队列。
  4. consumer group(CG):这是kafka用来实现一个topic消息的广播(发给所有人的consumer)和单播(发给任意一个consumer)的手段。一个topic可以有多个CG。topic的消息会复制(概念上的复制)到所有的CG,但每个partion只会把消息发给该CG中的一个consumer。如果需要实现广播,只要每个consumer有一个独立的CG就可以了。要实现单播只要所有的consumer在同一个CG。用CG还可以将consumer进行自由的分组而不需要多次发送消息到不同的topic。
  5. broker:一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。
  6. partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序。
  7. offset:kafka的存储文件都是按照offset.kafka来命名,用offset做名字的好处是方便查找。例如想找位于2049的位置,只要找到2048.kafka的文件即可。当然the first offset就是00000000000.kafka。

2、consumer与topic的关系

本质上kafka只支持topic。

每个group中可以有多个consumer,每个consumer属于一个consumer group。

通常情况下,一个group中会包含多个consumer,这样不仅可以提高topic中消息的并发消费能力,而且还能提高“故障容错”性,如果group中的某个consumer失效,那么其消费的partitions将会有其他consumer自动接管。

对于topic中的一条特定的消息,只会被订阅此topic的每个group中的其中一个consumer消费,此消息不会发送给一个group的多个consumer。

那么一个group中所有的consumer将会交错的消费整个topic,每个group中consumer消费互相独立,我们可以认为一个group是一个订阅者。

在kafka中,一个partition中的消息只会被group中的一个consumer消费(同一时刻);一个topic中的每个partitions,只会被一个“订阅者”中的一个consumer消费,不过一个consumer可以同时消费多个partitions中的消息。

kafka的设计原理决定,对一个topic,同一个group中不能由多于partitions个数的consumer同时消费,否则将意味着某些consumer将无法得到消息。

kafka只能保证一个partition中的消息被某个consumer消费时是顺序的;事实上,从topic角度来说,当有多个partions时,消息仍不是全局有序的。

3、kafka中生产数据的时候,如何保证写入的容错性。

设置发送数据是否需要服务端的反馈,有三个值:0、1、-1

0:producer不会等待broker发送ack。

1:当leader介绍到消息之后发送ack。

-1:当所有的follower都同步消息成功后发送ack。

三种机制,性能依次递减(producer吞吐量降低),数据健壮性则依次递增。

request.required.acks=0

4、如何保证kafka消费者消费数据是全局有序的。

伪命题

每个分区内,每条消息都有一个offset,故只能保证分区内有序。

如果要全局有序,必须保证生产有序,存储有序,消费有序。

由于生产可以做集群,存储可以分片,消费可以设置为一个consumer group,要保证全局有序,就需要保证每个环节都有序。

只有一个可能,就是一个生产者,一个partition,一个消费者。这种场景和大数据应用场景相悖。

5、分析广告投放对哪类用户更有效,如果数据是实时的呢,如何解决5分钟的误差

有两个数据源,一个记录的是广告投放给用户的日志,一个记录用户访问日志,另外还有一个固定的用户基础表记录用户基本信息(比如学历,年龄等等)。现在要分析广告投放对与哪类用户更有效,请采用熟悉的技术描述解决思路。另外如果两个数据源都是实时数据源(比如来自kafka),他们数据在时间上相差5分钟,需要哪些调整来解决实时分析问题?

可以使用flume+sqoop将数据源的数据拉取到hive中,统计广告投放用户的登陆数,对登陆数进行排名,分析排名分布,数据分布等等,如果不能简单判断,则可以按特征值分区统计登录数。如果有时间误差,可以根据时间戳进行时间分区(可能会至少有5分钟的延迟)。

6、kafka和sparkstreaming如何集成?

Receiver方式

Received是使用Kafka高级Consumer API实现的。与所有接收器一样,从Kafka通过Receiver接收的数据存储在Spark Executor的内存中,然后由Spark Streaming启动的job来处理数据。然而默认配置下,这种方式可能会因为底层的失败而丢失数据(请参阅接收器可靠性)。如果要启用高可靠机制,确保零数据丢失,要启用Spark Streaming的预写日志机制(Write Ahead Log,(已引入)在Spark 1.2)。该机制会同步地将接收到的Kafka数据保存到分布式文件系统(比如HDFS)上的预写日志中,以便底层节点在发生故障时也可以使用预写日志中的数据进行恢复。

Direct方式

在spark1.3之后,引入了Direct方式。不同于Receiver的方式,Direct方式没有receiver这一层,其会周期性的获取Kafka中每个topic的每个partition中的最新offsets,之后根据设定的maxRatePerPartition来处理每个batch。

这种方法相较于Receiver方式的优势在于:

简化的并行:在Receiver的方式中我们提到创建多个Receiver之后利用union来合并成一个Dstream的方式提高数据传输并行度。而在Direct方式中,Kafka中的partition与RDD中的partition是一一对应的并行读取Kafka数据,这种映射关系也更利于理解和优化。
高效:在Receiver的方式中,为了达到0数据丢失需要将数据存入Write Ahead Log中,这样在Kafka和日志中就保存了两份数据,浪费!而第二种方式不存在这个问题,只要我们Kafka的数据保留时间足够长,我们都能够从Kafka进行数据恢复。
精确一次:在Receiver的方式中,使用的是Kafka的高阶API接口从Zookeeper中获取offset值,这也是传统的从Kafka中读取数据的方式,但由于Spark Streaming消费的数据和Zookeeper中记录的offset不同步,这种方式偶尔会造成数据重复消费。而第二种方式,直接使用了简单的低阶Kafka API,Offsets则利用Spark Streaming的checkpoints进行记录,消除了这种不一致性。
请注意,此方法的一个缺点是它不会更新Zookeeper中的偏移量,因此基于Zookeeper的Kafka监视工具将不会显示进度。但是,您可以在每个批处理中访问此方法处理的偏移量,并自行更新Zookeeper。

7、列举kafka的优点,简述kafka为什么可以做到每秒数十万甚至上百万消息的高效分发?

优点

高吞吐量:每秒数十万、上百万的高效分发。

持久化数据存储:将消息持久化到磁盘,因此可以用于批量消费,防止数据丢失。

分布式系统易于扩展:所有的producer、broker和consumer都会有多个,均为分布式的。无需停机即可扩展机器。

客户端状态维护:消息被处理的状态是在consumer端维护,而不是由server端维护。但失败时能自动平衡。

高效率

虽然kafka会持久化所有数据到磁盘,当本质上每次写入操作其实都只是把数据写入到操作系统的页缓存,然后由操作系统自行决定什么时候把页缓存中的数据写回磁盘。

  1. 大量使用操作系统页缓存,内存操作速度快且命中率高。
  2. Kafka 不直接参与物理 1/0 操作,而是交由最擅长此事的操作系统来完成。
  3. 采用追加写入方式,摒弃了缓慢的磁盘随机读/写操作。
  4. 使用以sendfile为代表的零拷贝技术加强网络间的数据传输率。

8、为什么离线分析要用kafka?

kafka的作用是解耦,如果直接从日志服务器上采集的话,实时离线都要采集,等于要采集两份数据,而使用了kafka的话,只需要从日志服务器上采集一份数据,然后再kafka中使用不同的两个组读取就行了。

9、kafka怎么进行监控

使用kafka manager进行监控

下载kafka-manager。

并修改配置文件conf/application.conf,编写服务启动脚本。

启动集群及kafka manager,访问webui进行相关管理。

10、kafka与传统的消息队列服务有什么不同

快速持久化,可以在O(1)的系统开销下进行消息持久化;

高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;

完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现复杂均衡;

支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制来统一了在线和离线的消息处理

11、kafka api low-level与high-level有什么区别,使用low-level需要处理那些细节

High Level Consumer

屏蔽细节管理。

屏蔽了每个Topic的每个Partition的Offset管理(自动读取zookeeper中该Consumer group的last offset )。

Broker失败转移以及增减Partition、Consumer时的负载均衡(当Partition和Consumer增减时,Kafka自动进行负载均衡)。

对于多个Partition,多个Consumer。如果consumer比partition多,是浪费,因为kafka的设计是在一个partition上是不允许并发的,所以consumer数不要大于partition数,如果consumer比partition少,一个consumer会对应于多个partitions,这里主要合理分配consumer数和partition数,否则会导致partition里面的数据被取的不均匀。最好partiton数目是consumer数目的整数倍,所以partition数目很重要,比如取24,就很容易设定consumer数目。

如果consumer从多个partition读到数据,不保证数据间的顺序性,kafka只保证在一个partition上数据是有序的,但多个partition,根据你读的顺序会有不同。

增减consumer,broker,partition会导致rebalance,所以rebalance后consumer对应的partition会发生变化
High-level接口中获取不到数据的时候是会block的
关于Offset初始值的问题:
先produce一些数据,然后再用consumer读的话,需要加上一句offset读取设置

props.put("auto.offset.reset", "smallest"); //必须要加,如果要读旧数据  1

因为初始的offset默认是非法的,然后这个设置的意思 是,当offset非法时,如何修正offset,默认是largest,即最新,所以不加这个配置,你是读不到你之前produce的数据的,而且这个 时候你再加上smallest配置也没用了,因为此时offset是合法的,不会再被修正了,需要手工或用工具改重置offset。

Low Level API

细节需要自己处理。

控制灵活性,作为底层的Consumer API,提供了消费Kafka Message更大的控制,跳读,Exactly Once原语,提供更大灵活控制是以复杂性为代价的:Offset不再透明,Broker自动失败转移需要处理,增加Consumer、Partition、Broker需要自己做负载均衡,(Offset自己管理),如果一个Partition有多个副本,那么Lead Partition所在的Broker就称为这个Partition的Lead Broker。

12、kafka的ISR副本同步队列

ISR(In-Sync Replicas)副本同步队列。ISR中包括leader和follower。

ISR 中的副本都是与 Leader 同步的副本,相反,不在 ISR 中的追随者副本就被认为是与 Leader 不同步的。

Leader 副本天然就在 ISR 中。

**ISR 是一个动态调整的集合,而非静态不变的。**如果同步时间超过replica.lag.time.max.ms则被认为不是同步的,应该踢出该副本存入OSR(Outof-Sync Replicas),如果同步时间在replica.lag.time.max.ms之内,则应该加入队列。

默认只有在队列里面的(被认定是实时同步的follower副本)才可能被选举为leader。(这个原则可以通过修改对应的参数配置来改变)

13、kafka消息数据积压,kafka消费能力不足怎么处理?

  1. 如果是kafka消费能力不足,则可以考虑增加topic的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。
  2. 如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间<生产速度),使处理的数据小于生产的数据,也会造成数据积压。

14、kafka中的ISR、OSR、AR代表什么?

ISR(In-Sync Replicas):所有与leader副本保持一定程度同步的副本(包括Leader)组成ISR,ISR集合是AR集合中的一个子集。

OSR(Out-Sync Relipcas):与leader副本同步滞后过多的副本(不包括leader)副本,组成OSR。

AR(Assigned Repllicas):分区的所有副本。AR=ISR+OSR

15、kafka中的HW、LEO等分别代表什么?

LEO(Log End Offset):表示了当前日志文件中下一条待写入消息的offset。LEO的大小相当于当前日志分区中最后一条消息的offset值加1。

HW(High Watermak):表示了一个特定消息的偏移量(offset),消费者只能拉取到这个offset之前的消息。分区ISR集合中的每个副本都会维护自身的LEO,而ISR集合中最小的LEO即为分区的HW对消费者而言只能消费HW之前的消息

ps:

同步复制要求所有能工作的Follower副本都复制完,这条消息才会被确认为成功提交,这种复制方式影响了性能。

在异步复制的情况下, follower副本异步地从leader副本中复制数据,数据只要被leader副本写入就被认为已经成功提交。如果follower副本都没有复制完而落后于leader副本,如果突然leader副本宕机,则会造成数据丢失。

kafka使用ISR有效权衡了数据可靠性与性能之间的关系。

16、哪些情景会造成消息漏消费

先提交offset,后消费,有可能造成数据的重复

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

在执行完脚本之后,Kafka 会在 log.dir 或 log.dirs 参数所配置的目录下创建相应的主题分区,默认情况下这个目录为/tmp/kafka-logs/。

在 ZooKeeper 的/brokers/topics/目录下创建一个同名的实节点,该节点中记录了该主题的分区副本分配方案。

触发Controller的监听程序

kafka Controller负责topic的创建工作,并更新metadata cache

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

可以增加,使用 kafka-topics 脚本,结合 --alter 参数来增加某个主题的分区数,命令如下:

bin/kafka-topics.sh --bootstrap-server broker_host:port --alter --topic <topic_name> --partitions <新分区数>

当分区数增加时,就会触发订阅该主题的所有 Group 开启 Rebalance。
首先,Rebalance 过程对 Consumer Group 消费过程有极大的影响。在 Rebalance 过程中,所有 Consumer 实例都会停止消费,等待 Rebalance 完成。这是 Rebalance 为人诟病的一个方面。

其次,目前 Rebalance 的设计是所有 Consumer 实例共同参与,全部重新分配所有分区。其实更高效的做法是尽量减少分配方案的变动。
最后,Rebalance 实在是太慢了。

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

不支持,因为删除的分区中的消息不好处理。

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

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

有,__consumer_offsets,保存消费者offset

21、聊一聊Kafka Controller的作用?

controller主要依靠ZK完成对集群broker和分区的管理如集群broker信息、分区选举ISR等。

  1. 选举Leader和ISR
  2. 同步元数据信息包括broker和分区的元数据信息
  3. broker增删监听与处理
  4. topic变化监听与处理
  5. 分区变化监听与变化处理
  6. broker优雅退出

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

不能及时与leader同步,暂时踢出ISR,并加入OSR,等其追上leader之后再重新加入ISR。

23、kafka都有那些特点

高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition,consumer group对partition进行consume操作。

可扩展性:kafka集群支持热扩展

持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失

容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)。

高并发:支持数千个客户端同时读写。

24、请简述下你在那些场景下会选择kafka?

  1. 日志收集:一个公司可以用kafka收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、hbase、spark等。
  2. 消息系统:解耦生产者和消费者、缓存消息等。
  3. 用户活动跟踪:kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者转载到hadoop、数据仓库中做离线分析和挖掘。
  4. 运营指标:kafka而经常被用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
  5. 流式处理:比如spark streaming和flink。

25、kafka的设计架构你知道吗?

  1. Producer :消息生产者,就是向 kafka broker 发消息的客户端。
  2. Consumer :消息消费者,向 kafka broker 取消息的客户端。
  3. Topic :可以理解为一个队列,一个 Topic 又分为一个或多个分区。
  4. Consumer Group:这是 kafka 用来实现一个 topic 消息的广播(发给所有的 consumer)和单播(发给任意一个 consumer)的手段。一个 topic 可以有多个 Consumer Group。
  5. Broker :一台 kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个 broker 可以容纳多个 topic。
  6. Partition:为了实现扩展性,一个非常大的 topic 可以分布到多个 broker上,每个 partition 是一个有序的队列。partition 中的每条消息都会被分配一个有序的id(offset)。将消息发给 consumer,kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。
  7. Offset:kafka 的存储文件都是按照 offset.kafka 来命名,用 offset 做名字的好处是方便查找。例如你想找位于 2049 的位置,只要找到 2048.kafka 的文件即可。当然 the first offset 就是 00000000000.kafka。

26、kafka分区的目的?

分区对于kafka集群的好处:实现负载均衡。

分区对于消费者来说,可以提高并发度,提高效率。

producer可以将数据发送给多个broker上的多个partition,consumer也可以并行从多个broker上的不同paritition上读数据,实现了水平扩展 。

由于消息是以追加的形式添加到到分区中的,多个分区顺序写磁盘的总效率比随机写内存还要高

27、你知道kafka是如何做到消息的有序性?

kafka中的每个partition中的消息在写入时都是有序的,而且消息带有offset偏移量,消费者按偏移量的顺序从前往后消费,从而保证了消息的顺序性。

但是分区之间的消息是不保证有序的。

28、kafka的高可靠性是怎么实现的?

kafka通过分区的多副本机制来保证消息的可靠性。

  1. 每个分区可以设置多个副本,这些副本分布在不同的broker上;
  2. 相同partition的多个副本能动态选举leader来对外服务和管理内部数据同步。这样,即使有broker出现故障,受影响的partition也会在其它broker上重新选举出新的leader来继续服务。

29、请谈一谈kafka数据一致性原理

一致性就是说不论是老的 Leader 还是新选举的 Leader,Consumer 都能读到一样的数据。

所有在ISR中的副本都有个LEO(log end offset)偏移量,leader副本插入数据时,leaderLEO会增加,副本会复制leader新的数据,副本LEO也会增加,副本LEO不一样。

把ISR中的所有副本的最小LEO称为HW(high water mark),只有HW之前的数据才能被consumer消费。

producer端:

需要设置ack=all,如果发生leader出了问题,只有所有副本复制完成,producer才能写入成功,否则生产者会考虑重发消息。

consumer端:

因为consumer只能拉取HW之前的数据即ISR中所有副本都有的数据,所以如果此时发生leader选举,consumer不会拉取错误的数据,而是等到leader选举完成,HW发生变化,consumer才能重新消费。

使用HW这种模式兼顾了安全性和效率。当然主要还是用户按需求设置ack值。

30、ISR、OSR、AR是什么?

ISR:In-Sync Replicas副本同步队列

OSR:Out-of-Sync Replicas同步超时队列

AR:Assigned Replicas所有副本。AR=ISR+OSR

ISR是由leader维护,follower从leader同步数据有一些延迟,超过相应阈值会把follower踢出ISR,存入OSR列表,新加入的follower也会先存放在OSR中。

LEO:是LogEndOffset的简称,代表当前日志文件中下一条。

HW:水位或水印(watermark)一词,也可称为高水位(high watermark),通常被用在流式处理领域(如flink,spark等),以表征元素或事件在基于时间层面上的精度。在kafka中,水位的概念反而与时间无关,而是与位置信息相关。

严格来说他表示的就是位置信息,即唯一(offset)。取partition对应的ISR中最小的LEO作为作为HW,consumer最多只能消费到HW所在的位置上一条信息。

LSO:是LastStableOffset的简称,对未完成的事务而言,LSO的值等于事务中第一条消息的位置(firstUnstableOffset),对已完成的事务而言,他的值等他HW。

LW:low watermark低水位,代表AR集合中最小的logStartOffset值。

32、kafka在什么情况下会出现消息丢失?

  1. 自动提交
    设置offset为自动定时提交,当offset被自动定时提交时,数据还在内存中未处理,此时刚好把线程kill掉,那么offset已经提交,但是数据未处理,导致这部分内存中的数据丢失。
  2. 生产者发送消息
    发送消息设置的是fire-and-forget(发后即忘),它只管往 Kafka 中发送消息而并不关心消息是否正确到达。不过在某些时候(比如发生不可重试异常时)会造成消息的丢失。这种发送方式的性能最高,可靠性也最差。
  3. 消费者端
    先提交位移,但是消息还没消费完就宕机了,造成了消息没有被消费。自动位移提交同理
  4. acks没有设置为all
    如果在broker还没把消息同步到其他broker的时候宕机了,那么消息将会丢失

33.怎么尽可能保证 Kafka 的可靠性

  1. **topic级别:replication-factor>=3;
    **
  2. **producer级别:acks=-1;同时发送模式设置producer.type=sync;
    **
  3. broker级别:关闭不完全的leader选举,即unclean.leader.election.enable=false;

数据一致性

leader副本对外提供服务(写入和读出),leader写入的数据的位置称为LEO(logendoffset),其它follower副本也有LEO,随着同步leader的数据副本的LEO会慢慢和leader的LEO同步。

在ISR列表里面所有副本的LEO最小的叫做HW(HighWatermark),consumer读取数据只能读取HW之前数据,如果在此期间发生leader选举,选举期间leader服务不可用,直到完成后,新leader重新对外提供服务。

ps:

producer生产数据需要设置ack=-1,只有接收到所有副本的ack后才算完成写入操作即更新了HW。保证了producer和partition的数据一致,

如果发生leader选举,leader只会在ISR列表中产生,ISR最小的LEO是HW,consumer只能消费HW之前的数据。这种HW机制保证了partition和consumer的数据一致

34、消费者和消费者组有什么关系

  1. Consumer Group下可以有一个或多个Consumer实例。这里的实例可以是一个单独的进程,也可以是同一进程下的线程。在实际场景中,使用进程更为常见一些。
  2. topic主题会将消息发给所有订阅了的组。组内的实例轮流获取消息。
  3. 如果要将一个消息多播,则一个consumer group对应一个consumer,每个consumer都能获取消息,将同一份数据发送到不同系统。如果只是想让一个消息单播,则一个consumer group对应多个consumer,每个消息只有一个consumer获取,常见于需要增加消费能力的场景。

35.Kafka 的每个分区只能被一个消费者线程,如何做到多个线程同时消费一个分区?

  1. 线程封闭,即为每个线程实例化一个kafkaconsumer对象。一个线程对应一个kafkaconsumer实例,称之为消费线程。一个消费线程可以雄安飞一个或多个分区中的消息,所有的消费线程都隶属于同一个消费组。多线程+多kafkaconsumer实例
  2. 消费者程序使用单或多线程获取消息,同时创建多个消费线程执行消息处理逻辑。获取消息的线程可以是一个也可以是多个,每个线程维护专属的kafkaconsumer实例,处理消息则交由特定的线程池来做,从而实现消息获取与消息处理的真正解耦。单线程+单kafkaconsumer实例+消息处理worker线程池

37.Kafka 消费者是否可以消费指定分区消息?

可以。kafkaconsumer消费消息时,向broker发出fetch请求去消费特定分区的消息,consumer指定消息在日志中的偏移量(offset),就可以消费从这个位置开始的消息,customer拥有了offset的控制权,可以向后回滚去重新消费之前的消息,这是很有意义的。

38.Kafka消息是采用Pull模式,还是Push模式?

采用的pull模式。(producer将消息推送到broker,consumer从broker拉取消息。)

好处

consumer可以根据自己的消费能力进行消费,比如消费速率不一样,是否批量拉取数据。

缺点

如果broker没有可供消费的消息,将导致consumer不断在循环中轮询,直到消息到达。为避免这点,kafka有参数可以让consumer阻塞直到新消息到达。(也可以阻塞直到消息数量达到某个特定的量,实现批量发)

39、Kafka 消息格式的演变清楚吗?

v0版消息格式(kafka 0.10之前的版本)

crc32(4B):crc32校验值。校验范围为magic至value之间。 magic(1B):消息格式版本号,此版本的magic值为0。 attributes(1B):消息的属性。总共占1个字节,低3位表示压缩类型:0表示NONE、1表示GZIP、2表示SNAPPY、3表示LZ4(LZ4自Kafka 0.9.x引入),其余位保留。 key length(4B):表示消息的key的长度。如果为-1,则表示没有设置key,即key=null。 key:可选,如果没有key则无此字段。 value length(4B):实际消息体的长度。如果为-1,则表示消息为空。 value:消息体。可以为空,比如tomnstone消息。

v1版本(从0.10.0版本开始到0.11.0版本之前的版本)

v1版本比v0版本多一个8B的timestamp字段;

timestamp字段作用:
内部而言:影响日志保存、切分策略;
外部而言:影响消息审计、端到端延迟等功能的扩展

v2版本(0.11.0版本及之后的版本)

相对v0和v1改动较大,引入了变长整形Varints和ZigZag编码。

Varints作用:根据数值的大小,调整占用的字节数,数值越小,占用的字节数就越小
      0-63之间的数字占1个字节,64-8191之间的数字占2个字节,8192-1048575之间的数字占3个字节
      kafka broker的配置message.max.bytes的默认大小为1000012(Varints编码占3个字节)

ZigZag编码:使绝对值较小的负数仍然享有较小的Varints编码值

V2版本消息集称为Record Batch(v0和v1称为Message Set),相较于V0、V1版本

    (1)将多个消息(Record)打包存放到单个RecordBatch中,v2版本的单个Record Batch Header相较于v0、v1版本的多个Log_OVERHEAD(每个Record都会有1个LOG_OVERHEARD),会节省空间;
    (2)引入变长整形Varints和ZigZag编码,能够灵活的节省空间

40.Kafka 偏移量的演变清楚吗?

Kafka 0.10.x 对于非压缩的消息偏移量处理和 Kafka 0.8.x 一致,这里就不再介绍了。这里主要介绍 Kafka 0.10.x 对压缩消息偏移量处理逻辑。和 Kafka 0.8.x 处理内部消息偏移量逻辑不一样,这个版本对于内部消息偏移量使用的是相对偏移量,从0开始,依次到n-1,这里的n代表压缩消息的条数。

这个逻辑和 Kafka 0.8.x 处理逻辑一致,不再介绍。有一点需要注意,Kafka 0.10.x 会将消息的 magic 值设置为 1,用于区分其他版本的消息,后面会介绍这样设置的用处。

Broker 端接收到 Producer 发送过来的压缩消息,其也是先解压接收到的压缩消息,然后做一堆的判断,比如 消息的 magic 值是否大于0,压缩消息内部的消息偏移量值是否连续(0,1,2,3这样的)等,如果符合这些条件(inPlaceAssignment = true),那么 Broker 会直接处理整个压缩消息外部的偏移量,内部消息的偏移量不需要设置,因为这个在 Producer 端已经设置好了;并不需要再次压缩消息,最后会将这条消息追加到 Log 文件中。

如果 inPlaceAssignment = false,这时候会直接操作解压后的消息,并给压缩消息内部消息设置偏移量,最后设置整个压缩消息的偏移量;这时候会忽略掉 Producer 端为压缩消息设置的偏移量,包括内部消息和整个压缩消息的偏移量。整个处理逻辑分为两种情况:

(1)如果接收到的消息不是由 Kafka 0.10.x 版本Producer客户端发送过来的,那么消息的 magic 值会等于0,这时候 Broker 设置偏移量逻辑和 Kafka 0.8.x 处理逻辑一致,也就是不管内部消息还是整个压缩消息的偏移量都是使用绝对偏移量;

(2)如果接收到的消息是由 Kafka 0.10.x 版本Producer客户端发送过来的,那么消息的 magic 值会等于1,这时候 Broker 会将压缩消息内部的消息偏移量设置成相对的,从0开始,依次到 n-1 ,最后整个压缩消息的偏移量为nextOffset + n - 1,其中n为压缩消息的条数。

偏移量设置完之后,对于inPlaceAssignment = false,不管是由什么版本发送过来的消息, Broker 需要重新压缩刚刚解压好的消息,最后会将这条消息追加到 Log 文件中。

Client端对于压缩消息偏移量处理

对不同版本的 Client 请求, Broker 会做出不同的判断:对于非 Kafka 0.10.x 版本的 Consumer,Broker 端消息的发送不会使用零拷贝技术;而如果是 Kafka 0.10.x 版本的 Consumer,Broker 端消息的发送才会使用零拷贝技术

41.Kafka 高效文件存储设计特点

  1. Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
  2. 通过索引信息可以快速定位message和确定response的最大大小。
  3. 通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
  4. 通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小

42.Kafka创建Topic时如何将分区放置到不同的Broker中

  1. 副本因子不能大于 Broker 的个数;
  2. 第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的;
  3. 其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推;
  4. 剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的;

43.Kafka新建的分区会在哪个目录下创建

我们知道,在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。当然我们也可以配置 log.dir 参数,含义一样。只需要设置其中一个即可。

如果 log.dirs 参数只配置了一个目录,那么分配到各个 Broker 上的分区肯定只能在这个目录下创建文件夹用于存放数据。

但是如果 log.dirs 参数配置了多个目录,那么 Kafka 会在哪个文件夹中创建分区目录呢?答案是:Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。

44.谈一谈 Kafka 的再均衡(Rebalance)

在Kafka中,当有新消费者加入或者订阅的topic数发生变化时,会触发Rebalance(再均衡:在同一个消费者组当中,分区的所有权从一个消费者转移到另外一个消费者)机制,Rebalance顾名思义就是重新均衡消费者消费。Rebalance的过程如下:

第一步:所有成员都向coordinator发送请求,请求入组。一旦所有成员都发送了请求,coordinator会从中选择一个consumer担任leader的角色,并把组成员信息以及订阅信息发给leader。

第二步:leader开始分配消费方案,指明具体哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案发给coordinator。coordinator接收到分配方案之后会把方案发给各个consumer,这样组内的所有成员就都知道自己应该消费哪些分区了。

所以对于Rebalance来说,Coordinator起着至关重要的作用

45.谈谈 Kafka 分区分配策略

在 Kafka 内部存在两种默认的分区分配策略:Range 和 RoundRobin。当以下事件发生时,Kafka 将会进行一次分区分配:

  1. 同一个 Consumer Group 内新增消费者
  2. 消费者离开当前所属的Consumer Group,包括shuts down 或 crashes
  3. 订阅的主题新增分区

Range strategy

Range策略是对每个主题而言的,首先对同一个主题里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序。

然后将partitions的个数除于消费者线程的总数来决定每个消费者线程消费几个分区。如果除不尽,那么前面几个消费者线程将会多消费一个分区。

缺点:如果有n个主题,并且都不能整除,排序前面的消费者会比其它消费者进程多消费n个分区。

RoundRobin strategy

使用RoundRobin策略有两个前提条件必须满足:

  1. 同一个Consumer Group里面的所有消费者的num.streams必须相等;
  2. 每个消费者订阅的主题必须相同。

RoundRobin策略的工作原理:

将所有主题的分区组成 TopicAndPartition 列表,然后对 TopicAndPartition 列表按照 hashCode 进行排序。

最后按照round-robin风格将分区分别分配给不同的消费者线程。

因为根据hashcode排序,降低了同一个consumer分配到多个主题中的多余分区的概率。、

ps:

通过partition.assignment.strategy参数选择 range 或 roundrobin。partition.assignment.strategy参数默认的值是range。

推荐partition个数是consumer数的整数倍或者说consumer个数是partition个数的因子

46.Kafka Producer 是如何动态感知主题分区数变化的?

Kafka是分布式消息系统,需要处理海量的消息,Kafka的设计是把所有的消息都写入速度低容量大的硬盘,以此来换取更强的存储能力,但实际上,使用硬盘并没有带来过多的性能损失。kafka主要使用了以下几个方式实现了超高的吞吐率:

  1. 顺序读写
  2. 零拷贝
  3. 文件分段
  4. 批量发送
  5. 数据压缩。

48.Kafka 监控都有哪些?

比较流行的监控工具有:

KafkaOffsetMonitor

KafkaManager

Kafka Web Console

Kafka Eagle

JMX协议(可以用诸如jdk自带的jconsole来进行连接获取状态信息)

49.如何为Kafka集群选择合适的Topics/Partitions数量

针对kafka 1.1.0以及之后的版本,建议单台broker上partition数量不超过4000, 整个集群partition数量不超过2000,000,主要原因还是上面讲过的controller选举和controller重新选举partition leader的耗时。

相对kafka 1.1.0之前版本,这个parition数量已经有了很大提高,这全部得益于controller处理broker shutdown流程的优化,主要是针对zk的写操作异步化,批量化,将新的metadata通知给没有shutdown的broker也批量化,减少RPC次数,但是最最主要的,大家肯定想不到,是减少了不必要的log, 具体可参考Apache Kafka Supports 200K Partitions Per Cluster

50.谈谈你对 Kafka 事务的了解?

参见这篇文章:http://www.jasongj.com/kafka/transaction/

Kafka事务机制的实现主要是为了支持

  • Exactly Once即正好一次语义
  • 操作的原子性
  • 有状态操作的可恢复性

实现事务机制的几个阶段

  1. 幂等性发送

  2. 事务性保证

  3. 事务性消息传递

  4. 事务中Offset的提交

  5. 用于事务特性的控制型消息

  6. 事务过期机制

51.谈谈你对 Kafka 幂等的了解?

参见这篇文章:https://www.jianshu.com/p/b1599f46229b

Kafka在0.11.0.0版本支持增加了对幂等的支持。幂等是针对生产者的特性。幂等可以保证生产者发送的消息,不会丢失,而且不会重复。

如何实现幂等

HTTP/1.1中对幂等性的定义是:一次和多次请求某一个资源对于资源本身应该具有同样的结果(网络超时等问题除外)。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。

实现幂等的关键点就是服务端可以区分请求是否重复,过滤掉重复的请求。要区分请求是否重复的有两点:

  1. 唯一标识:要想区分请求是否重复,请求中就得有唯一标识。例如支付请求中,订单号就是唯一标识
  2. 记录下已处理过的请求标识:光有唯一标识还不够,还需要记录下那些请求是已经处理过的,这样当收到新的请求时,用新请求中的标识和处理记录进行比较,如果处理记录中有相同的标识,说明是重复交易,拒绝掉
Kafka幂等性实现原理

为了实现Producer的幂等性,Kafka引入了Producer ID(即PID)和Sequence Number。

  • PID。每个新的Producer在初始化的时候会被分配一个唯一的PID,这个PID对用户是不可见的。
  • Sequence Numbler。(对于每个PID,该Producer发送数据的每个<Topic, Partition>都对应一个从0开始单调递增的Sequence Number

Kafka可能存在多个生产者,会同时产生消息,但对Kafka来说,只需要保证每个生产者内部的消息幂等就可以了,所有引入了PID来标识不同的生产者。

对于Kafka来说,要解决的是生产者发送消息的幂等问题。也即需要区分每条消息是否重复。
Kafka通过为每条消息增加一个Sequence Numbler,通过Sequence Numbler来区分每条消息。每条消息对应一个分区,不同的分区产生的消息不可能重复。所有Sequence Numbler对应每个分区

Broker端在缓存中保存了这seq number,对于接收的每条消息,如果其序号比Broker缓存中序号大于1则接受它,否则将其丢弃。这样就可以实现了消息重复提交了。但是,只能保证单个Producer对于同一个<Topic, Partition>的Exactly Once语义。不能保证同一个Producer一个topic不同的partion幂等。

52.Kafka 缺点?

  1. 由于是批量发送,数据并非真正的实时;
  2. 对于mqtt协议不支持;
  3. 不支持物联网传感数据直接接入;
  4. 仅支持统一分区内消息有序,无法实现全局消息有序;
  5. 监控不完善,需要安装插件;
  6. 依赖zookeeper进行元数据管理;

53.Kafka 新旧消费者的区别

旧的 Kafka 消费者 API 主要包括:SimpleConsumer(简单消费者) 和 ZookeeperConsumerConnectir(高级消费者)。SimpleConsumer 名字看起来是简单消费者,但是其实用起来很不简单,可以使用它从特定的分区和偏移量开始读取消息。高级消费者和现在新的消费者有点像,有消费者群组,有分区再均衡,不过它使用 ZK 来管理消费者群组,并不具备偏移量和再均衡的可操控性。

现在的消费者同时支持以上两种行为,所以为啥还用旧消费者 API 呢?

54.Kafka 分区数可以增加或减少吗?为什么?

我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka 不支持减少分区数。

Kafka 分区数据不支持减少是由很多原因的,比如减少的分区其数据放到哪里去?是删除,还是保留?删除的话,那么这些没消费的消息不就丢了。如果保留这些消息如何放到其他分区里面?追加到其他分区后面的话那么就破坏了 Kafka 单个分区的有序性。如果要保证删除分区数据插入到其他分区保证有序性,那么实现起来逻辑就会非常复杂。

55.kafka消息的存储机制

kafka通过 topic来分主题存放数据,主题内有分区,分区可以有多个副本,分区的内部还细分为若干个 segment。都是持久化到磁盘,采用零拷贝技术。

1、高效检索

分区下面,会进行分段操作,每个分段都会有对应的素引,这样就可以根据 offset二分查找定位到消息在哪一段,根据段的索引文件,定位具体的 mle ssage

2、分区副本可用性(1 eader选举,zk来协调

如果1eader宕机,选出了新的1eader,而新的 leader并不能保证已经完全同步了之前1eader的所有数据,只能保证HW(高水位设置)之前的数据是同步过的,此时所有的 follower都要将数据截断到W的位置,再和新的 leader同步数据,来保证数据一致。

当宕机的 leader恢复,发现新的1eader中的数据和自己持有的数据不一致,此时宕机的1 eader会将自己的数据截断到宕机之前的hw位置,然后同步新1 eader的数据。宕机的1eader活过来也像 follower一样同步数据,来保证数据的一致性。

56.相比较于传统消息队列,kafka的区别

1、分区性:存储不会受单一服务器存储空间的限制

2、高可用性:副本1 eader选举

3、消息有序性:一个分区内是有序的。

4、负载均衡性:分区内的一条消息,只会被消费组中的一个消费者消费,主题中的消息,会均衡的发送给消费者组中的所有消费者进行消费。

57.消息丢失和消息重复

同步:这个生产者写一条消息的时候,它就立马发送到某个分区去。

异步:这个生产者写一条消息的时候,先是写到某个缓冲区,这个缓冲区里的数据还没写到 broker集群里的某个分区的时候,它就返回到 client去了

针对消息丢失:同步模式下,确认机制设置为-1,即让消息写入 Leader和 Fol lower之后再确认消息发送成功:

异步模式下,为防止缓冲区满,可以在配置文件设置不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态

针对消息重复,将消息的唯一标识保存到外部介质中,每次消费时判断是否处理过即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值