kafka面试题1
Posted lucky_xian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kafka面试题1相关的知识,希望对你有一定的参考价值。
这里写目录标题
- 1.消息队列的作用和使用场景:
- 2.使用消息队列会带来哪些问题:
- 3.如何做的消息队列选型,为什么选择kafka:
- 4.kafka相关概念与消费模型:
- 5.kafka的消息存储:
- 6.消费组与分区重平衡:
- 7.kafka如何保证不丢失消息:
- 8.kafka高可用:
- 9.kafka高性能原因:
- 10.Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么:
- 11.Kafka中的HW、LEO、LSO、LW等分别代表什么:
- 12.Kafka中是怎么体现消息顺序性的:
- 13.Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么:
- 14.Kafka生产者客户端的整体结构是什么样子的:
- 15.Kafka生产者客户端中使用了几个线程来处理,分别是什么:
- 16.Kafka的旧版Scala的消费者客户端的设计有什么缺陷:
- 17.消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?如果不正确,那么有没有什么hack的手段:
- 18.消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1:
- 19.有哪些情形会造成重复消费:
- 20.那些情景下会造成消息漏消费:
- 21.KafkaConsumer是非线程安全的,那么怎么样实现多线程消费:
- 22.简述消费者与消费组之间的关系:
- 23.当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑:
- 24.topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么:
- 25.topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么:
- 26.创建topic时如何选择合适的分区数:
- 27.Kafka目前有那些内部topic,它们都有什么特征?各自的作用又是什么:
- 28.优先副本是什么,它有什么特殊的作用:
- 29.Kafka有哪几处地方有分区分配的概念,简述大致的过程及原理:
- 30.简述Kafka的日志目录结构:
1.消息队列的作用和使用场景:
- 异步处理:
- 场景:用户注册账号后需要发送注册邮件和注册短信:
- 方案:引入消息队列将不是必须的业务逻辑,异步处理。
- 应用解耦:
- 场景:用户下订单后,订单系统需要通知库存系统,缺点是订单系统和库存系统耦合,如果库存系统无法访问,那么订单则减库存失败,导致用户下订单失败;
- 方案:引入消息队列进行应用解耦。
- 流量削锋:
- 场景:秒杀活动,会因为流量过大,导致流量暴增,应用挂掉
- 方案:引入消息队列控制活动的人数,缓解短时间内高流量压垮应用:
- 步骤:1.用户发出请求后,服务器接收,首先写入消息队列中,加入消息队列长度超过最大数量,则直接抛弃用户请求或者直接跳转到用户界面;2.秒杀业务根据消息队列中的请求消息,在做后续处理;
- 日志处理:
- 场景:将消息队列用在大量日志处理中,比如Kafka应用,解决大量日志传输问题;
- 步骤:
- 1.日志采集客户端,负责日志数据采集,定时写数据进入kafka队列;
- 2.Kafka消息队列,负责日志数据的接收存储与转发;
- 3.日志处理应用,订阅并消费Kafka队列中的日志数据;
参考博客:https://blog.csdn.net/seven__________7/article/details/70225830
2.使用消息队列会带来哪些问题:
- 问题:在系统的可用性,复杂性,一致性上带来了一些问题,在正常运行的系统中额外引入消息队列,如果引入的不合理(例如在数据量很小,结构很简单的系统引入消息队列),自然后引发系统可用性以及复杂性的问题;
- 一致性问题:
- 幂等性问题:若生产者端插入相同数据,或者消费者端将一条消息重复处理好几次,就会引入幂等性问题,kafka在解决这个问题时,在消费者端插入数据时,发送到broker的每批消息都赋予了一个序列号,用于系统去重,解决了生产者端的幂等性问题,消费者端可以在消息处理逻辑上保证幂等性(这个我还不是很熟悉机制);
- 消息可靠传输:对于kafka而言,如果客户端把消息发送给producer,就得到发送成功的响应,而produce并未把该消息发送给broker就崩溃了,那么这批数据就会丢失,或者发送给broker中的leader节点,ISR群组的其他节点并未收到消息,此时leader挂掉,也会引起消息丢失。故需要设置相关配置,详细情况可参考如下链接:
https://editor.csdn.net/md/?articleId=106603935#6_81 第6节
- 消息顺序性:kafka只能保证单个partition的顺序,若想topic全局有序,应该使用:一个topic,一个partition,一个consumer,单线程消费模式;
- 集群元数据一致性问题:kafka通过zookeeper保证集群元数据一致性问题;
参考资料:https://blog.csdn.net/qq_36236890/article/details/81174504?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
3.如何做的消息队列选型,为什么选择kafka:
- 1.kafka特点:
- 1.支持点对点以及发布订阅模式:Kafka的consumer group策略,同一个consumer group中的consumer不能同时订阅同一个partition,这实现了点对点策略,一个topic中的partition可以被不同的consumer group订阅,这是实现了发布订阅模式;
- 2.语言支持:支持多种语言,Java优先,新版本的produce和consumer都是用Java语言写的;
- 3.单机吞吐量:十万级,因为Kafka的写入策略是将消息写入到页缓存,写入内存速度自然是非常高的;
- 4.消息延迟:毫秒级,因为消息读取时首先从页缓存中进行命中,且采用了零拷贝策略,省略了消息传递时的IO时间,以及消息传递时再用户态和内核态切换的时间;
- 5.API完备性:高;
- 6.可用性:非常高,使用zookeeper实现,kafka中的元数据都存储在zookeeper的节点上,利用zookeeper的临时节点+watcher事件机制实现数据一致性,故可用性非常高;
- 7.消息丢失:可以配置produce端和consumer端的参数保证消息不会丢失;
- producer端:
- ack=all/-1:全部ISR中的服务器将消息写入到页缓存时给客户端返回相应消息;
- retire=Interger.MaAX_VALUE:全部ISR中的服务器将消息写入到页缓存时给客户端返回相应消息;
- max.in.flight.requests.per.connection=1:单次只能send一个消息给broker,避免消息分区offset错乱;
- 使用待回调机制的send发送消息;
- unclean.leader.election.enable=flase:不允许非ISR的节点被选举为leader;
- replication.factor=3:多副本保存;
- min.insync.replicas:ISR至少拥有的节点数量;
- replication.factor>min.insync.replicas;
- producer端:
- consumer端:
- enable.auto.commit = false:对消息进行处理后,再进行位移提交;
- 8.消息重复:理论上会有重复,但是kafka给重复消息赋了一个相同的ID来达到消息的幂等性;
- 9.文档完备性:高;
- 10.提供快速入门:高;
可参考 Apache Kafka 4.6章进行详细学习无消息配置。
4.kafka相关概念与消费模型:
- 消息:包含key值(分区,日志压实会使用),value值(存储实际的数据),timestamp(流式框架以及TTL会使用);
- broker:Kafka集群上的一个节点;
- topic:一个逻辑概念,代表了一类消息;
- partition:一个topic可以包含多个partition,每个partition的数据时单独存储的,offset也是单独维护的,Kafka引入partition的主要原因时为了提高吞吐量,Kafka三级存储模型为:topic-partition-message;
- consumer group:消费者组;
- 1.topic中的每条消息都只能被消费者组中的一个消费者所消费,一个topic可以被多个消费者订阅消费;
- 2.kafka为消费者组单独维护每个partition的消费位移;
- 3.consumer group是实现消费高可用的重要组件,一个consumer宕机,该消费者组会重新从组内选取另一个正常的consumer接替之前的consumer进行消费;
- 4.消费者组内的每个成员负责一定数量的分区,若有消费者离组,或者订阅的topic发生变动,或者订阅的topic的partition发生变动,会触发消费者组rebalance策略;
- offset:
- 1.分区offset:producer把消息发送给broker时,broker将消息写入底层log日志就会给每个消息分配一个分区offset,这个offset依次递增,在partition中的位置是不变的;
- 2.消费offset:Kafka会为每个消费者组为每个partition维护一份消费offset,表示该消息者组消费partition数据消费到什么进度,这个值是可变的,可以根据实际情况进行重置等操作;
- replica:为了保证Kafka集群数据的可靠性,Kafka使用了数据冗余机制,即创建了多个replica副本,副本分为两类:
- 1.leader replica:producer可以往里面写数据,consumer可以从leader中读取数据;
- 2.follower replica:不提供读写,只是被动的从leade副本获取数据与之保持同步,若leader宕机,follower副本会进行选举形成新的leader副本继续提供读写服务;
- ISR:与leader副本保持同步的replica集合,虽然kafka设置了多副本,单兵是所有副本都能追上leader副本的进度,如果因为个别副本追不上leader副本,leader副本不能更新HW值导致数据写不进去Kafka集群,必然降低卡夫卡集群的可用性,若忽略部分进度慢的节点,若leader宕机,新的leader变成进度慢的节点,则会丢失数据,所以要记录一些能追上leader进度的节点,这些节点集合就是ISR,leader节点永远在ISR中;
- pull消费模型:消费者向负责分区主动拉取消息,分区的消费偏移量通过Kafka内部默认的topic来记录,也可以显式指定;
- pull模型的优点:消费速度可以由消费者自由控制,broker设计更为简单;
5.kafka的消息存储:
- 1.log日志:Kafka的三级存储架构是——topic-partition-message,topic是逻辑概念,日志实际上是按照partition分区存储的,写入消息时按照key进行分区写入,写道broker的页缓存中,由操作系统刷新到底层文件系统中,数据日志.log按照事件顺序在尾部追加;
- 2.日志分段:为了避免日志多大引起的查询困难,数据日志.log在超过阈值则重建一个日志段进行写入,这就是日志分段处理;
- 3.索引日志:kafka设置了两种索引日志,.timeindex和.index,其中.index是按照位移记录的,.timeindex按照时间戳记录的,这两个索引文件不会记录每条消息,而是隔断记录,帮助用户快速定位到.log中的记录,里面的数据是消息offset和物理偏移地址的映射,查找的时候根据二分查找即可快速定位;
- 4.日志留存:Kafka可以为日志设置TTL,若日志数据存储时间超过TTL,则会进行清除,清楚单位是根据日志段进行清理的,将待删除日志段以及其索引日志全部删除;这个过程是异步的,Kafka会单独起一个线程进行清理工作;
- 5.日志压实:Kafka compaction保证每个分区下每个key的值职回保留最新记录,压实操作不会改变消息在分区日志中的offset,只会删除旧数据,会造成offset不连续,Kafka内部用于保存位移的,__consumer_offset就使用了日志压实,因为这时候用户完全不关心当前key的旧数据;
- 6.当前日志段:日志留存期设置不会对当前正在写入的日志段做处理,也可以通过配置参数的方式使日志压实部队当前日志段做处理;
6.消费组与分区重平衡:
- 1.消费者组:Kafka可以设置消费者组来消费partition中的数据,同一时间一个partition中的数据只能被一个消费者组中的一个消费者进行消费,一个topic可以被多个消费者组同时进行消费;
- 2.分区重平衡:消费者组会根据当前组内消费者的数量以及消费分区的数量来确定每个消费者分别消费哪些分区。
- 1.重平衡策略:
- 1.均分策略:消费者则先把所有的分区按顺序进行排列,然后按照消费者的数量算出每个消费者该消费N块,然后将这N块依次分配给消费者;
- 2.轮询策略:消费者则将所有分区按顺序进行排列,然后将分区轮询按照消费者当前负载分配给消费者,一次分配一个,直到分完为止;
- 3.黏度分配策略:前两种重平衡策略并未考虑上次分区分配和本次分配的关系,黏度分配可以在尽量保证上次分配策略不进行大变更的情况下,保证消费者消费情况的负载均衡;
- 2.触发时机:1.消费者离组;2.新的消费者进组;3.消费者订阅的topic数量发生变化,4.消费者订阅的topic的partition数量发生变化;
- 3.角色:
- 1.coordinator:由Kafka集群中的一个broker担任,负责协调rebalance工作
- 2.Leader consumer:由consumer集群中的一个consumer进行担任,负责指定分区消费方案;
- 4.场景:
- 1.新的consumer进组导致的rebalance:
- 1.新的consumer向coordinator发送JoinGroup信息,携带其订阅的topic信息;
- 2.coordinator通知新consumer所属的consumer group准备进行rebalance,清空组成员;
- 3.所有组成员向coordinator发送JoinGroup信息;
- 4.coordinator收到所有组成员的JoinGroup信息后,根据发送JoinGroup信息先后选出Leader consumer,然后将订阅的topic和分区信息发送给所有consumer;
- 5.Leader consumer收到topic及分区信息后,根据重平衡策略指定分区分配方案;
- 6.Leader consumer通过SyncGroup请求发送给coordinate,其他consumer也发送了分配方案,不过coordinate只以leader consumer的分配方案为准;
- 7.coordinate将分配方案作为SyncGroup请求的响应发送给所有conusmer,重平衡完成;
- 2.consumer离组导致的rebalance:
- 1.消费者发送leaveGroup请求给组协调者;
- 2.coordinator通知consumer group准备进行rebalance,清空组成员;
- 3.所有组成员向coordinator发送JoinGroup信息;
- 4.coordinator收到所有组成员的JoinGroup信息后,根据发送JoinGroup信息先后选出Leader consumer,然后将订阅的topic和分区信息发送给所有consumer;
- 5.Leader consumer收到topic及分区信息后,根据重平衡策略指定分区分配方案;
- 6.Leader consumer通过SyncGroup请求发送给coordinate,其他consumer也发送了分配方案,不过coordinate只以leader consumer的分配方案为准;
- 7.coordinate将分配方案作为SyncGroup请求的响应发送给所有conusmer,重平衡完成;
- 3.consumer崩溃导致的rebalance:
- 1.coordinator长时间收不到某个消费者的心跳信息;
- 2.coordinator通知consumer group准备进行rebalance,清空组成员;
- 3.所有组成员向coordinator发送JoinGroup信息;
- 4.coordinator收到所有组成员的JoinGroup信息后,根据发送JoinGroup信息先后选出Leader consumer,然后将订阅的topic和分区信息发送给所有consumer;
- 5.Leader consumer收到topic及分区信息后,根据重平衡策略指定分区分配方案;
- 6.Leader consumer通过SyncGroup请求发送给coordinate,其他consumer也发送了分配方案,不过coordinate只以leader consumer的分配方案为准;
- 7.coordinate将分配方案作为SyncGroup请求的响应发送给所有conusmer,重平衡完成;
- 1.新的consumer进组导致的rebalance:
- 1.重平衡策略:
7.kafka如何保证不丢失消息:
- 复制因子:Kafka可以通过配置复制因子来配置冗余副本,当复制因子大于1时,相同的数据就会存储多份,通过复制因子来达到数据的可靠性;
- ISR:ISR中的节点都是与leader节点保持同步的节点,当leader节点宕机崩溃时,会在ISR种选举出一个节点称为新的leader继续进行读写服务,并且不丢失数据;
- 其他参数:acks=-1/all:所有数据必须写入到所有ISR的log日志中,才算是完成提交;
8.kafka高可用:
- 1.角色:
- 1.zookeeper:保证Kafka中所有元数据的一致性,并为Kafka提供故障检查;
- 2.Controller:第一个注册到zookeeper目录/controller上的broker节点被选为controller,用于管理Kafka集群——包括更新集群元数据信息,创建topic,删除topic,分区重分配,优先副本选举,topic分区扩展,broker加入集群,broker崩溃,受控关闭,controller leader的选举等;
- 3.controller的高可用:利用zookeeper的临时节点和watcher机制实现,broker注册在/controller路径下的节点是一个临时节点,一旦controller所在的broker崩溃,该临时节点就会被删除,其他broker会在该路径下注册watcher机制,当临时节点删除后会触发watcher事件,其他节点就会向/controller目录下新建子节点,建立成功的broker成为新的controller,其他节点继续在/controller路径上注册watcher事件等大下一次崩溃重复该操作;
9.kafka高性能原因:
- 1.大量使用操作系统页缓存,内存操作速度快且命中率高(写数据就写在页缓存中,由操作系统自己进行刷盘,读取数据的时候也是先命中页缓存进行读取);
- 2.采用追加写入的方式,避免了低效的磁盘随机读写操作;
- 3.使用以sendfile为代表的零拷贝技术进行数据传输,省去了速度慢的IO层传输以及把数据从用户态切到内核态等操作;
- 4.数据写入采用了分区策略,日志段写入采用了分段策略,提高了数据读写的并发度;
- 5.建立了.index和.timeIndex两种索引,使消费者能快读定位到数据位置,提高数据读取效率;
- 6.生产者,消费者均支持批处理,提高了数据生产消费的吞吐量;
10.Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么:
- ISR:所有数据与Leader副本保持一致的副本,leader副本永远在ISR集合内,Kafka可以容忍ISR中至少还有一个broker时不丢数据,当leader副本宕机时,Kafka会从ISR中选择一个副本成为新的leader继续提供读写服务;
- AR:Kafka设置了复制因子,故一个数据会被冗余被分到多个broker中,这些备份数据partition组成的集合就被称为AR,这些备份集合会选择一个leader replica来进行数据读写,其他的作为follower replica被动的从leader中进行数据同步;
- ISR和AR的区别:AR中的副本不一定和leader副本保持一致,而ISR是必须保持一致的,ISR的数量不会多于AR,AR数量是所有replica的数量;
- ISR伸缩:ISR的作用就是保持leader的高可用,当leader宕机后能够从ISR中选择一个副本接替leader继续进行工作而不丢数据,故一条消息必须写入ISR所有副本才算写入成功。缩:若ISR中有一个节点崩溃或者因为频繁GC很难追上leader的进度,如果不从ISR中移除该节点,数据就难以写入,造成数据堵塞,因此要进行”缩“动作;伸:若ISR以外的节点赶上了Leader的进度,我们应该把它加回来ISR以保证ISR中的broker数量,故要进行"伸"动作;
11.Kafka中的HW、LEO、LSO、LW等分别代表什么:
- HW:取一个partition对应的LEO(对于follower副本,是取leader传入的HW和当前LEO中最小值)中最小的数据作为该partition的HW,消费者最多只能消费到HW前一条位移的数据;
- LEO:当前日志文件下一条要写入消息的offset,LEO指的offset数据不可读;
- LSO:对于未完成的事务而言,LSO指的是事务的第一条消息的offset,对于已完成的事务,LSO指的是HW位置;
- LW:代表AR集合的最小的LogStartOffset;
- 步骤演示Kafka如何更新HW和LEO:
- 1.假设当前集群只有一个leader和一个follower,且HW和LEO都等于0;
- 2.producer写入了一条数据进入leader,Leader将自己的LEO加1,此时Leader:LEO=1,HW=0,remoteLEO=0,Follower:LEO=0,HW=0;
- 3.follower向leader发送fetch请求;
- 4.leader读取底层log的位移,将offset=1发送给follower;
- 5.follower将数据写入到自己的底层log日志,并将自己的LEO置为1,此时:Leader:LEO=1,HW=0,remoteLEO=0,Follower:LEO=1,HW=0;
- 6.follower向leader再次发送fetch请求,该请求携带了follower的LEO=1的信息;
- 7.Leader收到该信后,将remoteLEO更新为1,因为leader中最小的LEO=1,故leader更新HW=1,并将此信息作为fetch的响应返回给follower,此时:Leader:LEO=1,HW=1,remoteLEO=1,Follower:LEO=1,HW=0;
- 8.follower读本的LEO和得到的HW都为1,此时更新follower副本的HW=1,则:Leader:LEO=1,HW=1,remoteLEO=1,Follower:LEO=1,HW=1;
可参考apache kafka实战书籍6.1.4节进行学习
12.Kafka中是怎么体现消息顺序性的:
- 1.Kafka中每个partition的消息在写入时都是有序的(其实不一定,如果开启了消息重试可能会导致消息乱序,要解决这个缺陷可以让消费者端send线程每次只发送一个消息);
- 2.消费时,每个partition只能被每个consumer group的一个consumer进行消费,这也保证了消费端的有序;
- 3.kafka是不能保证topic层面的消息有序的,如果需要保证,需要将topic的partition调整为1.
13.Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么:
- 1.分区器:Kafka会根据每条消息的key以及分区器逻辑对待发送消息进行分区,未定义key的消息使用轮询进行分区,默认分区器是计算key的hash决定分区,用户可以自己编写分区逻辑;
- 2.序列化器:Kafka会将key和value根据定义好的序列化机制序列化城二进制进行发送,因为broker中存储的就是二进制;
- 3.拦截器:Kafka使用拦截器在消息发送前或者producer回调前对消息进行一些定制化需求,producer允许用户定义多个拦截器形成拦截链;
- 4.顺序:一般来说,拦截器->序列化器->分区器,若拦截器的作用是对producer进行回调前对消息做定制化处理(sender IO线程内),顺序就是序列化器->分区器->拦截器了。
14.Kafka生产者客户端的整体结构是什么样子的:
- 生产者:
- 1.客户端构造properties对象,里面包括Kafka broker地址,key,value的序列化方式,以及其他参数赋值;
- 2.客户端使用properties对象创建KafkaProducer;
- 3.用户构建待发送的消息对象ProducerRecord,使用KafkaProducer进行发送;
- 4.发送到KafkaProducer中时,先对消息进行序列化,再根据key对消息进行分区,然后将消息按照分区放在缓冲区中等待发送(批量发送机制);
- 5.消息发送使用send线程进行处理,send线程在发送消息时要开辟一块缓冲将消息写入进行发送;
- 6.消息发送完成后,kafkaProducer会根据回调机制得到消息发送结果,若发送成功,可以得到一个MateData对象,里面含有key,value,其在分区日志的offset等等信息,否则就会返回报错。
- 客户端:
- 1.构造一个properties对象,至少指定bootstrap.servers,key的解序列化方式,value的解序列化方式,以及group.id的值;
- 2.使用properties实例构造KafkaConsumer对象;
- 3.调用KafkaConsumer.subscribe方法订阅consumer group感兴趣的topic列表;
- 4.循环调用consumer的poll方法送partition分区中拉取消息进行消费,若设置自动提交位移,则在拉取消息成功后就会自动提交位移;
- 5.处理得到的ConsumerRecord对象,若设置手动提交位移,业务逻辑处理完要进行位移提交;
- 6.关闭KafkaConsumer对象;
15.Kafka生产者客户端中使用了几个线程来处理,分别是什么:
- 两个,主线程和sender线程;
- 主线程:负责创建消息,序列化消息,对消息进行分区,将消息放在缓冲池中积累消息进行批量发送,若设置有拦截器也会处理拦截器的逻辑;
- sender线程:从缓冲池中拿到消息发送给broker;
16.Kafka的旧版Scala的消费者客户端的设计有什么缺陷:
- 1.api不好用,设置了high-level consumer和low-level consumer,low-level consumer甚至不能自动处理故障转移;
- 2.consumer在内部使用多线程,逻辑锅鱼复杂,新版使用单线程+selector机制从多个分区中拉取消息;
- 3.旧版本consumer将消费端offset提交给zookeeper,若数据量特别大,zookeeper的性能就会成为瓶颈,且zookeeper是一个保证一致性的组件,并不适合做这样繁杂的数据读写操作;
17.消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?如果不正确,那么有没有什么hack的手段:
- 正确的,同一时间一个partition里的数据不能同时被一个消费者组的多个消费者进行消费;
- 若要使得空闲的consumer被使用,可以增加topic的分区数量,或者使得当前consumer group多订阅几个topic,再设置均衡的分区分配策略,这样就不会有consumer是空闲的了;
18.消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1:
- 消费者提交的位移是当前消费道德最新消息的offset+1;
19.有哪些情形会造成重复消费:
- 消费者使用了手动提交位移,从partition上拉取到了ConsumerRecord后,进行了逻辑处理,还没来得及提交offset,当前consumer就崩溃了,然后consuemr group根据分区平衡策略进行了rebalance,另一个正常工作的consumer继续消费当前partition,然后从之前的offset上重新拉取消息进行处理,就会造成重复消费;
20.那些情景下会造成消息漏消费:
- 消费者使用了自动提交位移,从partition上拉取到了ConsumerRecord后,还未进行了逻辑处理,就提交offset,当前consumer就崩溃了,然后consuemr group根据分区平衡策略进行了rebalance,另一个正常工作的consumer继续消费当前partition,然后从新的offset上重新拉取消息进行处理,就会造成消息漏消费;
21.KafkaConsumer是非线程安全的,那么怎么样实现多线程消费:
- 1.为每个线程创建一个consumer:每个consumer从partition中拉取消息交给其对应的线程进行处理。
- 优点:逻辑简单,实现简单,速度快,方便位移管理;
- 缺点:1.consumer的扩展(即线程的扩展)取决于partition数量,不能无限扩展;2.每个consumer都会创建一个socket,许多socket给broker端造成一定压力;3.consumer过多容易触发consumer rebalance机制;
- 2.将消息获取和消息处理解耦:使用一个consumer从partition上拉取数据,然后将拉取到的消息放在线程池中进行处理,位移的提交也有线程池中的线程池进行;
- 优点:消息获取和消息处理解耦,线程数可以独立扩展,伸缩性比较好;
- 缺点:实现复杂,位移提交复杂,难以维护分区内的消息顺序,若worker线程异常,可能导致整个线程池所有线程都不可用;
22.简述消费者与消费组之间的关系:
- 从属:消费者组由消费者组成,一个消费者组可以包含多个消费者;
- 特点:1.一个consumer group中的consumer同一时间内不能同时消费一个partition,2.一个topic可以被多个消费者组进行订阅;
- 消费者:用于实现从partition中拉取消息进行消费的应用程序;
- 消费者组:consumer端进行负载均衡以及故障转移的组件;
- 1.故障转移:若组内其中一个consumer宕机,conusmer group会将它所承载的partition通过rebalance分配给其他消费者进行消费;
- 2.负载均衡:consumer会根据分区分配策略将分区均匀的分配给consumer进行消费;
- 消息模型范式:
- 点对点模型:一个consumer group中的consumer同一时间内不能同时消费一个partition;
- 发布/订阅模型:一个topic可以被多个消费者组进行订阅;
23.当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑:
- 增加节点:
- 1.该删增加操作会使Kafka向/brokers/topics目录下新增代表该topic的znode节点;
- 2.将该topic的分区以及其对应的副本列表写入到这个znode逻辑中;
- 3.contoller通过watcher时间监听到该路径下子节点的变更情况,触发topic创建逻辑;
- 4.contoller为topic的每个partition确定leader和ISr,然后更新集群的元数据信息;
- 5.contoller创建watcher事件来监控/brokers/topics/<新增topic>节点下的变更;
- 删除节点:
- 1.该删除操作会使Kafka向/admin/delete_topics目录下新增代表该topic的znode节点;
- 2.contoller通过watcher时间监听到该路径下子节点的变更情况,开启删除topic的逻辑;
- 3.Kafka的controller会停止该topic下的所有副本;
- 4.删除所有副本的日志数据以及元数据信息;
- 5.删除/admin/delete_topics/<待删除topic节点>,删除工作正式完成;
24.topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么:
- 可以增加;
- 增加方式:使用Kafka-topics脚本的–alter选项来完成;
25.topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么:
- 不可以减少分区数;
- 原因:会造成数据的丢失,产生数据不一致问题,这是由于kafka的底层设计决定的,减少分区,就会删除该分区下的.log数据,就算不删除,consumer也没有办法订阅该partition进行数据消费;
26.创建topic时如何选择合适的分区数:
- 1.根据集群节点数量进行分区创建,分区不要超过集群节点数量,否则会报错;
- 2.根据实际的吞吐量来创建,实际的吞吐量不大的话不要创建过多分区,不然数据均匀分布在多个节点上,提高了系统的复杂性;
27.Kafka目前有那些内部topic,它们都有什么特征?各自的作用又是什么:
- 内部topic:__consumer_offsets;
- 特征:
- 1.Kafka自行创建的,不可以被删除;
- 2.Key:topic-patition-group_id三元组;Value:offset;
- 3.自动使用了压实操作,只为每个key保存最新的offset消息;
- 4.总共有50个,用于分散__consumer_offsets的写入负载,写入时对group_id进行取模运算得到其对应的__consumer_offsets;
- 作用:
- 用于保存Kafka集群上consumer group消费各个partition的位移信息;
28.优先副本是什么,它有什么特殊的作用:
- 优先副本:Kafka内部对每一个partition的副本所在的broker进行排序,将排序结果进行存储,优先副本为该排序结果中最靠前并且可用的那一个broker;
- 作用:为了Kafka中的负载均衡,Kafka只能使用leader进行读写,follower replica只能被动的从leader上同步数据,故producer和consumer请求全部落在了leader副本所在的broker上,若一个broker上含有多个leader,其他broker上没有,就会造成卡夫卡集群中的负载不均衡,优先副本机制:可以让优先队列中靠前的副本称为leader,能保证leader均匀的分布在Kafka集群的各个节点中,起到负载均衡的效果;
29.Kafka有哪几处地方有分区分配的概念,简述大致的过程及原理:
- 1.创建topic是进行分区分配:
- 1.指定机架的分配策略;
- 2.未指定机架的分配策略;
注:此处不是很懂,不详述。
- 2.consumer group消费数据是进行分区分配:
- 1.range策略:基于范围的思想,将单个topic的所有分区按照顺序排列,然后把这些分区划分成固定大笑的分区段并依次分配给consumer;
- 2.round-robin策略:基于轮询的思想,把所有topic的所有分区顺序掰开,然后轮询式分配给各个consumer;
- 3.sticky策略:采用了由黏性的策略对所有conusmer实例进行分配,可以规避极端情况下的数据倾斜,并且在两次rebalance间最大限度的维持了之前的分配方案;
30.简述Kafka的日志目录结构:
- 1.每个partition都有一个文件夹,包含四类文件:.index .log .timeindex leader-epoch-checkpoint ;
- 2…index .log .timeindex 三个文件成对出现,前缀为上一个segment的最后一个消息的偏移位置;
- 3.log文件中保存了所有的消息 index文件中保存了稀疏的相对偏移的索引 timeindex保存的则是时间索引;
- 4.leader-epoch-checkpoint中保存了每一任leader开始写入消息时的offset 会定时更新 follower被选为leader时会根据这个确定哪些消息可用;
以上是关于kafka面试题1的主要内容,如果未能解决你的问题,请参考以下文章