首页 > 编程知识 正文

kafka原理和面试笔试题目,activemq面试题

时间:2023-05-03 07:04:42 阅读:31362 作者:598

提问“Nq DBq博客”中的Kafka面试问题全套整理|积分报考!

Nq数据库管理员提出了一个问题。 以下是我对这些问题的解答。

文章目录Kafka的用途是什么? 使用场景怎么样? Kafka的ISR、AR代表了什么? 所谓ISR的伸缩,Kafka的HW、xsdbl、LSO、LW等分别代表着什么? 在Kafka中是如何表现消息的顺序性的? 你知道Kafka的分区、串行化器和拦截器吗? 它们之间的处理顺序是什么? Kafka生产者客户端使用了多少个线程? 分别是什么? Kafka生产者客户端的总体结构是什么? Kafka的旧Scala消费者客户端设计有什么缺点? 元数据是什么? “如果消费群体的消费者数量超过topic的划分,消费者就无法消费数据”这句话是正确的吗? 如果不正确的话,有什么hack的手段吗? 消费者在提交消费班次时提交的是当前消费的最新信息的offset吗? 还是offset 1? 生产者问题消费者问题在什么情况下会引起重复消费? 在那些场景中信息会消失吗? 既然KafkaConsumer是非线程安全的,该如何实现多线程消费? 简述消费者与消费群体关系wxdys使用kafka-topics.sh创建(删除) topic后,Kafka背后会运行什么逻辑? 可以增加topic的分区数吗? 怎么才能增加呢? 如果做不到,那是为什么? 可以减少topic的分区数吗? 怎么才能减少呢? 如果做不到,那是为什么? 创建topic时如何选择适当的分区数? Kafka目前有它们的内部主题。 它们有什么特征? 各自的作用是什么? 首选副本是什么? 有什么特别的作用? Kafka有分区分配的概念吗? 简要说明大致过程和原理的Kafka的用途是什么? 使用场景怎么样? Kafka的ISR、AR代表了什么? ISR的伸缩是什么

分区中的所有副本统称为关联副本(ar )。 与leader的副本(包括leader )同步的所有副本都构成了同步复制(ISR ),它是AR集合的子集。 与leader副本同步太晚的副本(leader除外)构成了不同步(osr ),因此可以看到AR=ISR OSR。

ISR伸缩:

leader拷贝将保留和跟踪ISR集合中所有follower拷贝的延迟状态,如果follower拷贝延迟或过期,则将其从ISR集合中排除。 如果OSR集合中的所有follower副本都“赶上”leader副本,leader副本会将其从OSR集合传输到ISR集合【副本可以在OSP,ISR之间来回移动】。

Kafka的硬件、xsdbl、LSO、LW等分别代表什么? 记录偏移(lso )开始偏移。

“低水位”(lw )低水位表示“ar”(assigned replica )集合中最小的“lso”(logstartoffset )起始偏移量。

xsd bl:(日志结束偏移。 表示当前日志文件中下一个要写入的消息的offset。

HW:(HighWatermark )俗称高水位,分区中所有副本最小的偏移。 ISR集合中最小的xsdbl是分区的HW,对消费者来说只能消耗HW以前的信息。

在Kafka中是如何表现消息的顺序性的? Kafka只能保证分区中消息的顺序,而不能保证全局顺序。 因为消息将发送到不同的分区,并且无法保证在分区之间发送的顺序。

写入时,分区的消息按顺序写入。

消费时,一个划分同时只被消费群体内的一个消费者消费,保证消费时也有秩序。

你知道Kafka的分区、串行化器和拦截器吗? 它们之间的处理顺序是什么? 1 .拦截器)生产者拦截器可以在发送消息之前做一些准备工作,例如根据某些规则过滤不合格的消息或修改消息的内容,也可以在发送回调逻辑之前做一些客户工作,例如统计工作

2 .串行化器:将java对象转换为字节数组并在网络上传输

3 .分区管理器:确定消息将发送到中介上的哪个分区。

拦截器-串行化器-分区

Kafka生产者客户端使用了多少个线程? 分别是什么? 整个生产者客户端主要包括两个线程、主线程和Sender线程。 Producer在主线程上生成消息,通过拦截器、串行化器和分区,然后缓存在消息累加器RecordAccumulator中。 Sender线程从RecordAccumulator检索消息并将其发送到kafka。

Kafka生产者客户端的总体结构是什么?

主线程发送器线程消息累加器

上一次会议中提到了主线程、Sender线程。

RecordAccumulator主要用于缓存消息,Sender线程可以发送大量消息,从而减少网络传输的资源消耗并提高性能。 从主线程发送的消息将回收到RecordAccumulator中的一个Deque中,并在RecordAccumulator中为每个分区维护两个Deque。 队列的内容是ProducerBatch,即Deque。

Kafka的旧Scala消费者客户

端的设计有什么缺陷? 元数据是指什么?

元数据是指Kafka集群的元数据,这些元数据具体记录了集群中有哪些主题,这些主题有哪些分区,每个分区的leader副本分配在哪个节点上,follower副本分配在哪些节点上,哪些副本在AR、ISR等集合中,集群中有哪些节点,控制器节点又是哪一个等信息。

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

正确,一个分区只能交给一个消费者消费,所有的分区都有对应的消费者消费,剩余的消费者自然没有分区可以消费。

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

当前消费者需要提交的消费位移并不是offset,而是offset+1,对应于上图中的 position,它表示下一条需要拉取的消息的位置。

生产者问题

Producer发送消息到队列,分区Leader收到消息后返回ACK给Producer,表示接收成功,此时可以继续发送下一笔消息。

Kafka提供了3种不同级别的ACK机制:

acks为0时, 表示生产者将数据发送出去就不管了,不等待任何确认就返回。这种情况下数据传输效率最高,但是数据可靠性最低,当 server挂掉的时候就会丢数据;acks为1时(默认),表示数据发送到Kafka后,leader成功接收消息,发送者收到确认,才算发送成功,如果leader在同步给其他副本之前宕机了,还是会丢失数据。acks为-1/all时,表示生产者需要等待ISR中的所有follower都确认接收到数据后才算发送完成,这样数据不会丢失,因此可靠性最高,性能最低。如果ISR只有一个副本就退化成了ack=1的情况了。 消费者问题

Consumer进行消费时,提交Offset偏移给Kafka记录消费的最新位置。 提交Offset有以下2种方式:

自动提交:enable.auto.commit 设置 true 开启,auto.commit.interval.ms 设置自动提交的频率间隔。Consumer获取到消息就提交Offset,不管消费是否成功手动提交:enable.auto.commit 设置 false ,消费完成后再调用 consumer.commit(),手动更新Offset。如果消费失败,我们可以将异常记录进行人工干预,然后再提交Offset,避免影响后面消息的消费。 有哪些情形会造成重复消费? producer到broker数据因为网络问题,发送重复数据导致consumer消费重复先消费的数据,还没有提交offset 宕机了Producer的ACK设置-1,没收到ACK进行重新发送,导致重复了

解决办法:为了避免重复,我们需要在发送消息的时候增加一个唯一的标识字段。例如:订单ID、订单号。 Consumer消费成功后,将该标识记录在Redis等媒介。下次消费的时候,先判断当前标识如果已经存在,直接跳过;如果不存在,再进行消费

那些情景下会造成消息漏消费?

丢不丢数据指的是producer到broker的过程,以及broker存储数据的过程。重复消费、漏消费指的是消费结果

Producer的ACK等级设置0或者1,可能因为没落盘或者没同步Follower,leader宕机导致丢失Consumer设置自动提交,消费失败来不及记录异常就宕机,但是Offset提交了,导致丢失 KafkaConsumer是非线程安全的,那么怎么样实现多线程消费?

Kafka的生产者KafkaProducer是线程安全的,然而消费者KafkaConsumer却是非线程安全的。
第一种方式:线程封闭

即为每个线程实例化一个KafkaConsumer对象(KafkaConsumer对象是什么?)
一个线程对应一个KafkaConsumer实例,可以称之为消费线程。一个消费线程可以消费一个或多个分区中的消息,所有的消费线程都隶属于同一个消费组,这种实现方式的并发度受限于分区的实际个数。
这种多线程的实现方式和开启多个消费进程的方式没有本质上的区别,优点是每个线程可以按顺序消费各个分区的消息。缺点也很明显,每个消费线程都要维护一个独立的TCP连接,如果分区数和consumerThreadNum的值都很大,那么会造成系统比较大的开销。

第二种方式:处理消息模块改成多线程

poll()拉取消息的速度是相当快的,而整体消费的瓶劲是在处理消息这一块,如果通过一定的方式来改进这一部分,那么就能带动整体消费的性能提升。那么可以考虑如下实现方式,将处理消息模块改成多线程的实现:(消息处理模块是什么?)
第二种实现方式相比第一种实现方式而言,除了横向扩展的能力,还可以减少TCP连接系统资源的消耗,不过缺点就是对于消息的顺序处理就比较困难了。
解决办法是,每一个处理消息的RecordHandler类在处理完消息之后都将对应的消费位移保存到共享变量offsets中,KafkaConsumerThread在每一次poll()方法之后都读取offsets中的内容并对其进行位移提交。注意在实现的过程中对offsets读写需要加锁处理,防止出现并发问题;并且在写入offsets的时候需要注意位移覆盖的问题。
但这种位移提交的方式还是会有数据丢失的风险。对于同一个分区中的信息,假设一个处理线程RecordHandler1正在处理offset为099的消息,而另一个处理线程RecordHandler2已经处理完成了offset为100~199的消息并进行了位移提交,此时如果RecordHandler1发生异常,则之后的消费只能从200开始而无法再次消费099的消息,从而造成了消息丢失的现象。这里虽然针对位移覆盖做了一定的处理,但还没有解决异常情况下的位移覆盖问题,对此就要引入更加复杂的处理机制。

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

每个消费者都有一个对应的消费组。每一个分区只能被一个消费组中的一个消费者所消费,同一个消费组中消费者不会重复消费同一个分区。

消费者与消费组这种模型可以让整体的消费能力具备横向伸缩性,我们可以增加(或减少)消费者的个数来提高(或降低)整体的消费能力。对于分区数固定的情况,一味地增加消费者并不会让消费能力一直得到提升,如果消费者过多,出现了消费者的个数大于分区个数的情况,就会有消费者分配不到任何分区。

消费组是一个逻辑上的概念,它将旗下的消费者归为一类,每一个消费者只隶属于一个消费组。每一个消费组都会有一个固定的名称,消费者在进行消费前需要指定其所属消费组的名称,这个可以通过消费者客户端参数 group.id 来配置,默认值为空字符串。

消费者并非逻辑上的概念,它是实际的应用实例,它可以是一个线程,也可以是一个进程。同一个消费组内的消费者既可以部署在同一台机器上,也可以部署在不同的机器上。

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

当创建一个主题时,实质是在Zookeeper中的/brokers/topics节点下创建与该主题对应的子节点并写入主题相关的配置信息。
当删除一个主题时,本质上只是在ZooKeeper中的/admin/delete_topics 路径下创建一个与待删除主题同名的节点,以此标记该主题为待删除的状态。与创建主题相同的是,真正删除主题的动作也是由Kafka的控制器负责完成的。

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

可以

玩命的汉堡/kafka-topics.sh --zookeeper localhost:2181/kafka --alter --topic topic-config --partitions 3

上面这个命令会有告警信息,当主题中消息包含key时,根据key计算分区的行为会受到影响,原本发往分区0的消息会被发往分区1,2 对于基于key计算的主题而言,建议一开始设置好分区数量。

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

不可以,kafka只支持增加分区数而不支持减少分区数。
此功能完全可以实现,不过也会使代码的复杂度急剧增大。
考虑删除的分区中的消息如何处理,如果随着分区一起删除则消息的可靠性得不到保障,如果分散插入现有的分区,那么在消息量很大的时候,内部的数据复制会占用很大的资源,而且在复制期间,此主题的可用性又如何得到保障?如果直接存储到现有分区尾部,消息的时间戳就不会递增,如果分散插入现有的分区,内部的数据复制会占用很大的资源。与此同时,顺序性问题、事务性问题,以及分区和副本的状态机切换问题都是不得不面对的。
反观这个功能的收益点却是很低的,如果真的需要实现此类功能,则完全可以重新创建一个分区数较小的主题,然后将现有主题中的消息按照既定的逻辑复制过去即可。

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

从吞吐量方面考虑,增加合适的分区数可以在一定程度上提升整体吞吐量,但超过对应的阈值之后吞吐量不升反降。如果应用对吞吐量有一定程度上的要求,则建议在投入生产环境之前对同款硬件资源做一个完备的吞吐量相关的测试,以找到合适的分区数阈值区间。

再比如对于同一个key 的所有消息,消费者需要按消息的顺序进行有序的消费,如果分区的数量发生变化,那么有序性就得不到保证。在创建主题时,最好能确定好分区数,这样也可以省去后期增加分区所带来的多余操作。尤其对于与key高关联的应用,在创建主题时可以适当地多创建一些分区,以满足未来的需求。

Kafka目前有那些内部topic,它们都有什么特征?各自的作用又是什么?

__consumer_offsets和__transaction_state
__consumer_offsets 叫位移主题,即 Offsets Topic,主要作用是保存 Kafka 消费者的位移信息。
老版本 Consumer 的位移管理是依托于ZooKeeper 的,它会自动或手动地将位移数据提交到 ZooKeeper 中保存,但ZooKeeper 并不适用于这种高频的写操作,因此,使用 Kafka 主题来保存位移。
位移主题的消息格式是 Kafka 自己定义的,用户不能修改,一旦写入的消息不满足 Kafka 规定的格式,那么 Kafka 内部无法成功解析,会造成 Broker 的崩溃。
__consumer_offsets 参考:https://blog.csdn.net/qq_41049126/article/details/111311816

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

优先副本: 一个分区副本集合的第一个副本称之为优先副本。比如主题 topic-partitions 中分区 0的AR集合列表(Replicas)为[1,2,0],那么分区0的优先副本即为1。
优先副本的选举: 通过一定的方式促使优先副本选举为leader副本,以此来促进集群的负载均衡,这一行为也可以称为“分区平衡”。
优先副本的作用
从某种程度上说,broker 节点中 leader 副本个数的多少决定了这个节点负载的高低。如果leader分布过于集中,就会造成集群负载不均衡。为了让系统负载均衡,我们总是需要让leader副本尽可能均匀地分布到 Kafka 集群的各个broker节点上。kafka系统broker节点会出现异常,lead副本会常常变换,解决方式是把优先副本作为leader副本,维护优先副本在Kafka集群中均匀分布,就是维护leader副本在各节点的均匀性。

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

生产者分区分配: 为生产者确定消息发往哪个分区。
消费者分区分配: 为消费者确定去哪个分区取消息。
创建主题分区分配: 为主题确定在哪些节点broker创建哪些分区副本。
创建主题分区分配根据副本分配参数的有无划分为两种,有直接按照副本分配参数创建,没有则按照内部逻辑计算分配方案,内部逻辑根据机架信息又划分为两种模式。

分区副本再次进行合理的分配,也就是所谓的分区重分配。
分区重分配的基本原理是先通过控制器为每个分区添加新副本(增加副本因子),新的副本将从分区的leader副本那里复制所有的数据。根据分区的大小不同,复制过程可能需要花一些时间,因为数据是通过网络复制到新副本上的。在复制完成之后,控制器将旧副本从副本清单里移除(恢复为原先的副本因子数)。注意在重分配的过程中要确保有足够的空间。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。