目录
- [消息队列 / Kafka 的好处](#消息队列 / Kafka 的好处)
- 消息队列的两种模式
- [什么是 Kafka](#什么是 Kafka)
- [Kafka 优缺点](#Kafka 优缺点)
- [你在哪些场景下会选择 Kafka](#你在哪些场景下会选择 Kafka)
- [讲下 Kafka 的整体结构](#讲下 Kafka 的整体结构)
- [Kafka 工作原理 / 流程](#Kafka 工作原理 / 流程)
- [Kafka为什么那么快/高效读写的原因 / 实现高吞吐的原理](#Kafka为什么那么快/高效读写的原因 / 实现高吞吐的原理)
- 生产者如何提高吞吐量(调优)
- [kafka 消息数据积压,消费者如何提高吞吐量](#kafka 消息数据积压,消费者如何提高吞吐量)
- 说一下Kafka生产者如何生产数据,消费者如何消费数据
- [Kafka 中的数据是有序的吗,如何保证有序性?](#Kafka 中的数据是有序的吗,如何保证有序性?)
- 指定partition的话,如果发生了数据倾斜,一个key的数据全发到了一个partition会出现什么问题
- [Kafka 中是如何实现消息的有序的](#Kafka 中是如何实现消息的有序的)
- [Kafka Producer Batch](#Kafka Producer Batch)
- [broker 的工作流程](#broker 的工作流程)
- [Kafka 的单播和多播](#Kafka 的单播和多播)
- 生产者消息为什么分区
- 生产者分区策略
- Kafka分区分配的概念?
- 消费者分区分配策略
- [Kafka 分区数可以增加或减少吗](#Kafka 分区数可以增加或减少吗)
- [kafka 如果有台机器挂掉会发生什么](#kafka 如果有台机器挂掉会发生什么)
- Kafka在哪些地方会有选举过程,使用什么工具支持选举?
- Kafka中Producer,Broker,Cousumer的关系
- [Kafka 怎么保证数据不丢失 / 可靠性 ***](#Kafka 怎么保证数据不丢失 / 可靠性 ***)
- Kafka解决两个客户端消费数据的问题
- Kafka分区多副本机制?
- [Kafka数据的一致性如何保证 ***](#Kafka数据的一致性如何保证 ***)
- Kafka一个生产者可以把消息发到多个分区吗?
- Kafka集群为什么挂掉一个broker后还能工作
- Kafka设置ack=-1时一定会保证消息不丢失吗
- [Kafka Follower如何与Leader同步数据](#Kafka Follower如何与Leader同步数据)
- Kafka日志保存时间
- Kafka单条日志的传输大小
- Kafka消息的消费方式?
- Kafka消息存储机制
- [Kafka 的 ISR、OSR 和 AR](#Kafka 的 ISR、OSR 和 AR)
- [说下 Kafka 的 ISR 机制](#说下 Kafka 的 ISR 机制)
- [Kafka 的 ack 有几种值 / ack 机制](#Kafka 的 ack 有几种值 / ack 机制)
- [Kafka的 offset 管理](#Kafka的 offset 管理)
- 消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?
- 如果有一条offset对应的数据,消费完成之后,手动提交失败,如何处理?
- Kafka为什么同一个消费者组的消费者不能消费相同的分区?
- 正在消费一条数据,Kafka挂了,重启以后,消费的offset是哪一个
- 为什么需要消费者组
- 有哪些情形会造成重复消费
- 有哪些情形会造成消息漏消费
- 当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑?
- [Kafka读取消息 Pull 模式的优缺点](#Kafka读取消息 Pull 模式的优缺点)
- Kafka的消费者组是如何消费数据的
- [Kafka 消费者是否可以消费指定分区消息](#Kafka 消费者是否可以消费指定分区消息)
- [Kafka 零拷贝技术](#Kafka 零拷贝技术)
- kafka服务器默认能接收的最大消息是多少
- Kafka新建的分区会在哪个目录下创建
- 数据传输的事务有几种
- Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?
- Kafka生产者客户端的整体结构是什么样子的?使用了几个线程来处理?分别是什么?
- "消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据"这句话是否正确?
- 失效副本是指什么?有那些应对措施?
- [kafka 有几种数据保留的策略?](#kafka 有几种数据保留的策略?)
- [聊一聊Kafka Controller的作用?](#聊一聊Kafka Controller的作用?)
- [如果我指定了一个offset,Kafka Controller 怎么查找到对应的消息?](#如果我指定了一个offset,Kafka Controller 怎么查找到对应的消息?)
- 简述Kafka的日志目录结构?
- [kafka中的 zookeeper 起到什么作用,可以不用zookeeper么](#kafka中的 zookeeper 起到什么作用,可以不用zookeeper么)
- Kafka消费者如何消费多分区
- Raft
消息队列 / Kafka 的好处
(1)缓冲/消峰:有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况;
(2)解耦:允许独立的扩展或修改两边的处理过程,只要确保它们遵守相同的接口约束;
(3)异步通信:允许用户把一个消息放入队列,但并不立即处理它,然后在需要的时候再去处理它们。
消息队列的两种模式
(1)点对点(一对一)
(2) 发布/订阅(一对多)
什么是 Kafka
Kafka是由 Apache 开发的一个分布式的基于发布订阅模式的消息队列,主要应用于大数据的实时处理领域。
Kafka 优缺点
优点
- 高吞吐量、低延迟: Kafka 可解耦数据流,因此延迟非常低,速度极快。即使在非常廉价的机器上,Kafka也能做到每秒处理几十万条消息,而它的延迟最低只有几毫秒。
- 可扩展性:Kafka 集群支持热扩展。Kafka 的分区日志模型允许跨多个服务器分发数据,使其可扩展性超越了在单服务器上应用的情况。
- 持久性、可靠性: 分区可以跨多个服务器分发和和复制,数据全都写入到磁盘。这有助于防止服务器发生故障,使数据获得出色的容错能力和耐久性。
- 容错性:允许集群中节点故障(若副本数量为n,则允许n-1个节点故障)。
- 高并发:支持数千个客户端同时读写。
缺点
- 仅支持统一分区内消息有序,无法实现全局消息有序;
- 监控不完善,需要安装插件;
- 由于是批量发送,数据并非真正的实时;
- 依赖zookeeper进行元数据管理。
你在哪些场景下会选择 Kafka
(1)在系统或应用程序之间构建可靠的用于传输实时数据的管道,消息队列功能
(2)构建实时的流数据处理程序来变换或处理数据流,数据处理功能
讲下 Kafka 的整体结构
(1)Producer:消息生产者,负责向Broker发送消息
(2)Consumer:消息消费者,从负责Broker读取并消费消息
(3)Consumer Group(CG):消费者组,由多个consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个消费者消费;消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
(4)Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic。
(5)Topic :主题,使用Topic对消息进行分类,Kafka接收到的每条消息都会放入到一个Topic中。
(6)Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,对Topic的数据进行分布式存储的最小单位。
(7)Replica:副本,为保证集群中的某个节点发生故障时,该节点上的partition数据不丢失,且kafka仍然能够继续工作,kafka提供了副本机制,一个topic的每个分区都有若干个副本,一个leader和若干个Follower。
(8)Leader:每个分区多个副本的"主",生产者发送数据的对象,以及消费者消费数据的对象都是leader。
(9)Follower:每个分区多个副本中的"从",实时从leader中同步数据,保持和leader数据的同步。leader发生故障时,某个Follower会成为新的leader。
Kafka 工作原理 / 流程
Kafka中消息是以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的。topic是逻辑上的概念,而partition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据。Producer生产的数据会被不断追加到该log文件末端,且每条数据都有自己的offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个offset,以便出错恢复时,从上次的位置继续消费。
Kafka为什么那么快/高效读写的原因 / 实现高吞吐的原理
Kafka 的数据在log文件中,是保存在磁盘上。
(1)Kafka本身是分布式集群,并且采用分区技术,并行度高
(2)读数据采用稀疏索引,可以快速定位到要消费的数据
(3)写 log 文件的时候,一直是追加到文件末端,是顺序写 的方式,官网中
说了,同样的磁盘,顺序写能达到 600M/s,而随机写只有 100K/s
(4)实现了零拷贝技术,只用将磁盘文件的数据复制到页面缓冲区一次,然后将数据从页面缓冲区直接发送到网络中,这样就避免了在内核空间和用户空间之间的拷贝
生产者如何提高吞吐量(调优)
(1)batch.size:批次大小,默认 16k,即一次发送消息的批次大小。增大批次大小可以减少单个请求的次数,提高吞吐量。
(2)linger.ms:等待时间,调整等待时间可以让生产者等待更多的消息一起发送,减少请求的频率。
(3)compression.type:压缩 snappy(解压缩速度快,压缩率也还行)
(4)RecordAccumulator:缓冲区大小,增大 RecordAccumulator 的缓冲区大小可以积累更多的消息,减少发送请求的频率。
kafka 消息数据积压,消费者如何提高吞吐量
(1)如果是 Kafka 消费能力不足,则可以考虑增加 Topic 的分区数,并且同时提升消费组的消费者数量,消费者数=分区数。 ( 两者缺一不可)
(2)如果是下游的数据处理不及时,提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间 < 生产速度),使处理的数据小于生产的数据,也会造成数据积压。
- fetch.max.bytes:指定了每次拉取消息的最大字节数。增大这个值可以提高每批次拉取的数据量,加快数据的处理速度。
- max.poll.records:指定了每次拉取请求返回的最大消息数。增大这个值可以一次性获取更多的消息,从而提高每批次处理的数据量。
说一下Kafka生产者如何生产数据,消费者如何消费数据
Kafka生产者写入(生产)数据流程
- 生产者先从Zookeeper的 "/brokers/topics/主题名/partitions/分区名/state"节点找到该 partition 的Leader
- 生产者在Zookeeper中找到该ID找到对应的broker
- broker进程上的Leader将消息写入到本地log中
- Follower从Leader上拉取消息,写入到本地log,并向Leader发送ACK
- Leader接收到所有的ISR中的Replica的ACK后,并向生产者返回ACK
Kafka消费者消费数据流程
- 通过Zookeeper找partition对应的Leader位置以及offset,Leader是负责读的
- 找到该分区的Leader,拉取数据
- 然后开始从offset往后顺序从本地log中读取数据
- 消费者提交offset(自动提交------每隔多少秒提交一次offset、手动提交------放入到事务中提交)
Kafka 中的数据是有序的吗,如何保证有序性?
kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在分区内部保证消息的顺序性。但是分区之间的消息是不保证有序的。
解决办法:
- 设置topic有且仅有一个分区
- 从业务上把需要有序的打到同一个 partition (指定相同的分区号或者使用相同的 key)
指定partition的话,如果发生了数据倾斜,一个key的数据全发到了一个partition会出现什么问题
partition倾斜就是热点倾斜,会导致消息堆积,可以通过hash算法或者亲缘性线程池去解决,但是亲缘性线程池也有热点倾斜问题,最本质的方式是对每个message的hash处理。
亲缘性线程池:针对某些需要保持数据顺序处理或特定数据之间存在关联的情况,可以使用亲缘性线程池来确保相关数据被分配到同一个线程或任务中处理,从而避免热点倾斜问题(避免了频繁的线程切换,减少网络通信开销)。
Kafka 中是如何实现消息的有序的
生产者:通过分区的 leader 副本负责数据以先进先出的顺序写入,来保证消息顺序性。
消费者:同一个分区内的消息只能被一个 group 里的一个消费者消费保证分区内消费有序。
Kafka Producer Batch
Kafka Producer Batch是指Kafka生产者在向Broker发送消息时可以一次性发送多条消息,减少网络传输的开销和提高消息发送的效率。在新建ProducerBatch时需要评估这条消息的大小是否超过batch.size,如果不超过,就以batch.size的大小来创建这个ProducerBatch,这样在使用完后还可以通过BufferPool的管理进行复用。若果超过,则以消息的大小来创建ProducerBatch,此内存区域不会被复用。
broker 的工作流程
在Kafka集群中,broker 指 Kafka 服务器。
(1)broker 启动后在 zk 注册
(2)Kafka 集群中的 broker 都到 zk 的 controller 节点集群注册,谁先注册,哪个broker 就成为controller 。
(3)选举出来的 controller 监听brokers 节点的变化
(4)controller决定Leader选举
(5)controller 将节点信息上传至 zk
(6)其他的 broker 从 zk 同步相关信息
(7)假设 broker1 中的 Leader 挂掉了
(8)controller 监听到节点变化
(9)controller获取该Leader的 ISR 队列
(10)选举新的Leader(以在ISR中存活为前提,按照在AR中排在前面的优先)
(11)更新Leader以及ISR
Kafka 的单播和多播
单播:一条消息只能被同一个消费者组中的一个消费者消费;
多播:一条消息能被多个消费者组中的消费者共同消费
生产者消息为什么分区
(1)可以提高并发 ,因为可以以 Partition
为单位读写了。(分区也是 Kafka 高效读写数据的主要原因)
(2)对于 Kafka 集群的好处是可以实现负载均衡
生产者分区策略
分区的原因
- 方便在集群中扩展,每个
Partition
可以通过调整以适应它所在的机器,而一个 topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了;- 可以 提高并发 ,因为可以以
Partition
为单位读写了。(分区也是 Kafka 高效读写数据的主要原因)
(1)既没有 partition
值又没有 key
值的情况下, kafka 采用 Sticky Partition
(黏性分区器),会随机选择一个分区,并 尽可能一直使用该分区,待该分区达到了batchsize大小或者默认发送的时间,kafka 再随机一个分区进行使用,只要与上一个分区不同即可。
(2)没有指明 partition
值但有 key
的情况下,将 key
的 hash
值与 topic
的 partition
数进行取余得到 partition
值;
(3)指明 partition
的情况下,直接将指明的值直接作为 partiton
值;
(4)自定义分区器:实现 Partitioner 接口,重写 partition 方法
Kafka分区分配的概念?
一个 consumer group 中有多个 consumer,一个 topic 有多个 partition,所以必然会涉及到 partition 的分配问题,即确定那个 partition 由哪个 consumer 来消费。
消费者分区分配策略
Kafka 有三种分配策略,Range
(范围分区) ,RoundRobin
(轮询分区),Sticky
(粘性分区)。
Range
:(针对每个 topic 而言的)首先对同一个 topic 里面的分区按照序号进行排序,并对消费者按照字母顺序进行排序,然后用分区数除以消费者数,得到每个消费者消费几个 partition,然后按分区顺序连续分配若干 partition ,除不尽的话前面几个消费者会多分配一个分区的数据。- 问题:如果只是针对 1个 topic,消费者 0 多消费一个分区影响不大;但是如果有 N个 topic,那么消费者 0 就会多消费 N 个分区,那么就容易发生数据倾斜。(该分配策略适用于topic少的情况)
- 再平衡:挂掉了一个消费者之后,45 秒以内重新发送消息,此时剩余的消费者暂时不能消费到挂掉的消费者应该消费的分区,等到了45 秒以后,消费者就真正的挂掉了,此时会把它应该消费的分区数都分配给某个消费者
RoundRobin
:(针对所有 topic) 首先将所有 partition 和 consumer 都列出来,然后按照 hashcode 排序,最后通过轮询算法来分配 partition 给到各个消费者。- 再平衡:进行轮询
Sticky
:尽量均匀的分配分区给消费者(随机),黏性体现在在执行新的分配之前,考虑上一次的分配结果,尽量少的变动,这样就可以节省大量的开销。- 再平衡:均匀分配
Kafka 分区数可以增加或减少吗
我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka 不支持减少分区数。
Kafka 分区数据不支持减少是由很多原因的,比如减少的分区其数据放到哪里去?是删除,还是保留?删除的话,那么这些没消费的消息不就丢了。如果保留这些消息如何放到其他分区里面?追加到其他分区后面的话那么就破坏了 Kafka 单个分区的有序性。如果要保证删除分区数据插入到其他分区保证有序性,那么实现起来逻辑就会非常复杂。
kafka 如果有台机器挂掉会发生什么
(1)follower故障
follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步。等该follower的LEO大于等于该Partition的HW,即follower追上leader之后,就可以重新加入ISR了。
(2)leader故障
leader发生故障之后,会从ISR中选出一个新的leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据。
Kafka在哪些地方会有选举过程,使用什么工具支持选举?
Kafka中Producer,Broker,Cousumer的关系
一条消息从生产到消费,可以划分三个阶段:
- 生产阶段:Producer 创建消息,并通过网络发送给 Broker。
- 存储阶段:Broker 收到消息并存储,如果是集群,还要同步副本给其他 Broker。
- 消费阶段:Consumer 向 Broker 请求消息,Broker 通过网络传输给 Consumer。
Kafka 怎么保证数据不丢失 / 可靠性 ***
一条消息从生产到消费,可以划分三个阶段:
- 生产阶段:Producer 创建消息,并通过网络发送给 Broker。
- 存储阶段:Broker 收到消息并存储,如果是集群,还要同步副本给其他 Broker。
- 消费阶段:Consumer 向 Broker 请求消息,Broker 通过网络传输给 Consumer。
这三个阶段都可能丢失数据,所以要保证消息丢失,就需要任意一环都保证可靠。
生产阶段
- ACK机制
- ack=0、ack=1 都有丢失数据的风险。
- ack=all/-1 意味着会等待所有同步副本都收到消息。再结合 min.insync.replicas ,就可以决定在得到确认响应前,至少有多少副本能够收到消息。
存储阶段
- 每个 broker 中的 partition 我们一般都会设置有 replication (副本),的个数,生产者写入的时候首先根据分区分配策略(有 partition 按 partition,有 key 按 key,都没有轮询)写入到 leader 中,follower(副本) 再跟 leader 同步数据,这样有了备份,也可以保证消息数据的不丢失。
消费阶段
- 消费者消费数据的时候会不断提交 ofset,就是消费数据的偏移量,以免挂了,下次可以从上次消费结束的位置继续消费。
Kafka解决两个客户端消费数据的问题
在Kafka中,同一个消费者组内的消费者可以共同消费一个或多个分区的数据。这种方式被称为分区分配。Kafka通过负载均衡来实现分区分配,确保一个分区只由一个消费者组内的消费者来消费。如果在同一个消费者组内有多个消费者,每个消费者可以独立地读取分区数据,并且每个分区只会被分配给一个消费者。这样就能够实现分布式消费数据的效果,同时也保证了消费者读取到的数据是有序的。如果一个消费者挂掉了,那么它所消费的分区将会重新分配给其他消费者,确保数据的高可靠性和可用性。
Kafka分区多副本机制?
Kafka为分区引入了多副本(Replica)机制,通过增加副本数量可以提升容灾能力。同一分区的不同副本中保存的是相同消息(在同一时刻,副本之前并非完全一样),副本之间是"一主多从"的关系,其中leader副本负责处理读写请求,follower副本只负责与leader副本的消息同步。副本处于不同的broker中,当leader副本出现故障时,从follower副本中重新选举新的leader副本对外提供服务。Kafka通过多副本机制实现了故障的自动转义,当Kafka集群中某个broker失效时扔然能够保证服务可用。
Kafka数据的一致性如何保证 ***
不论是旧的Leader还是新选举产生的Leader,Consumer都能读到一样的数据,Kafka是通过引入HW(High Water Mark)机制来保证数据一致性。
每个副本都有一个HW和一个LEO,LEO是每个副本最大的 offset,HW 则是所有副本中最小的LEO,即该Partition对外服务的最大 offset。
Kafka一个生产者可以把消息发到多个分区吗?
支持将不同消息发往多个分区,但是同一消息只能发往某一分区。
Kafka集群为什么挂掉一个broker后还能工作
Kafka使用了副本机制,每个分区的数据会被复制到多个broker上,即使某个broker挂掉,其他broker上的副本也能继续服务,确保了整个集群的可用性。
Kafka设置ack=-1时一定会保证消息不丢失吗
与ack=1或0相比,当其他环境相同的情况下,ack设置为-1/all可以达到最强的可靠性,但这并不意味这消息就一定可靠,因为ISR中可能只有Leader副本,这就成了ack=1的情况,所有此时是不安全。
Kafka的Broker端提供了一个参数min.insync.replicas,该参数控制的是消息至少被写入到多少个副本才算是"真正写入",该值默认值为1,生产环境设定为一个大于1的值可以提升消息的持久性,因为如果同步副本的数量低于该配置值,则生产者会收到错误响应,从而确保消息不丢失。
所以想要获得更高的可靠性,需要配合min.insync.replicas等参数的联动,才能尽量保证消息不丢失。
Kafka Follower如何与Leader同步数据
为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack,如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。
Kafka日志保存时间
默认7天
Kafka单条日志的传输大小
默认为单条消息最大值是 1M,但是在我们应用场景中,常常会出现一条消息大于 1M 的情况,如果不对 kafka 进行配置,则会出现生产者无法将消息推送到 kafka 中或消费者消费不到 kafka 里面的数据的情况。我们可以配置两个参数:一个是副本的最大值,一个是单条消息的最大值,来解决消息最大限制的问题。
- message.max.bytes=1M:这个参数用来设置单条消息的最大大小
- replica.fetch.max.bytes=1M:这个参数用来设置副本同步单条消息的最大大小
Kafka消息的消费方式?
Pull 模式。又针对该模式的缺点提出了 timeout 机制
(1)push模式:以消费者最低的消费速率来推送
-
缺点:可能会造成资源的浪费
-
优点:每次推送一定是有新消息的
(2)pull模式:消费者主动拉取消息,拉取时是不知道有没有新消息的
-
缺点:如果Kafka没有数据,消费者可能会陷入循环中,一直返回空数据
-
优点:可以根据消费者的消费能力以适应当前的速率消费消息。
Kafka消息存储机制
kafka 中的消息就是 topic,topic 只是逻辑上的概念,而 partition 才是物理上的概念,每个 partition 对应一个 log 文件,它存储的就是 producer 生产的数据。生产者生产的数据会不断追加到 log 文件中,如果 log 文件很大了,就会导致定位数据变慢。因此 kafka 采取了分片和索引的·机制,将大的 log 文件分为多个 segment,每个 segment 会对应.log 文件和.index 文件和.timeindex 文件,.log 存储数据,.index 存储偏移量索引信息,.timeindex 存储时间戳索引信息。
- .index 为稀疏索引,大约每往 log 文件写入 4kb 数据,会往 index 文件写入一条索引。
- Index 文件中保存的 offset 为相对 offset,这样能确保 offset 的值所占空间不会过大
Kafka 的 ISR、OSR 和 AR
ISR(InSyncRepli):内部副本同步队列;
OSR(OutSyncRepli):外部副本同步队列;
AR(AllRepli):所有副本,AR = ISR + OSR;
任意一个超过延迟时间阈值的 follower 都会被剔除出 ISR,存入 OSR 列表,新加入的 follower 也会先存放在OSR中。
说下 Kafka 的 ISR 机制
为避免因某个副本的 follower 故障不能同步数据而造成 leader 一直等待,leader 维护了一个列表,为保持同 leader 同步的 follower 集合,该集合中副本和 leader 相差数据不超过一个阈值(可设置),超出一定时间数据未达到该阈值,则 follower 会被踢出 ISR。ISR 主要在 leader 出现故障后作为选举新 leader 的备用池。
Kafka 的 ack 有几种值 / ack 机制
Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的 acks 参数配置:
- 0:这一操作提供了一个最低的延迟,partition的 leader 接收到消息还没有写入磁盘就已经返回 ack,当 leader 故障时有可能丢失数据;
- 1: partition的 leader 落盘成功后返回ack,如果在follower同步成功之前 leader 故障,那么将会丢失数据;
- -1(all): partition 的 leader 和 follower 全部落盘成功后才返回 ack。但是如果broker发送 ack 之前,leader 发生故障,那么会造成数据重复。
Kafka的 offset 管理
Kafka 0.9 版本之前,consumer 默认将 offset 保存在 Zookeeper 中,从 0.9 版本开始,consumer 默认将 offset 保存在 Kafka 一个内置的 topic 中,该 topic 为__consumer_offsets
消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?
offset+1
如果有一条offset对应的数据,消费完成之后,手动提交失败,如何处理?
可以给offset提交设置失败后重复提交,如果依旧提交失败,就要进行人工干预了
Kafka为什么同一个消费者组的消费者不能消费相同的分区?
因为这样可能会消费到重复的消息 ,因为 kafka 的 log 文件对应的数据都会存储自己的偏移量,而它是按照消费者组,主题,分区来进行区分的,那么同一个消费者组中的消费者使用的就是同一份偏移量,这样就很容易消费到重复的消息。
kafka的offset不是为单个消费者存的,是为消费者组存的。
正在消费一条数据,Kafka挂了,重启以后,消费的offset是哪一个
当Kafka服务器挂掉时,消费者正在消费的offset会保存在消费者所在的客户端内存中,并且会定期定时地将消费的offset提交到Kafka集群中。如果此时Kafka服务器挂掉,那么消费者无法将消费的offset提交到Kafka集群中,此时消费者的offset并没有被记录到Kafka集群中,也就是说,在Kafka服务器重启后,消费者的offset会被重置到上一次提交的offset位置,而不是当前正在消费的offset位置。
为什么需要消费者组
消费者组的好处:
- 消费效率更高
- 消费模式灵活
- 便于故障容灾
有哪些情形会造成重复消费
消费者消费后没有提交offset(程序崩溃/强行kill/消费耗时/自动提交偏移情况下unsubscrible)。
有哪些情形会造成消息漏消费
消费者没有处理完消息就提交offset(自动提交偏移 未处理情况下程序异常结束)。
当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑?
创建
(1)会在zookeeper中的/brokers/topics节点下创建一个新的topic节点,如:/brokers/topics/first
(2)触发Controller的监听程序
(3)kafka Controller 负责topic的创建工作,并更新metadata cache
删除
调用脚本删除topic会在zk上将topic设置待删除标志,kafka后台有定时的线程会扫描所有需要删除的topic进行删除,也可以设置一个配置server.properties的delete.topic.enable=true直接删除
Kafka读取消息 Pull 模式的优缺点
优点:灵活控制消费速率;批量拉取提高效率。
缺点:需要消费者不断进行主动拉取,会增加网络负担;消费者长时间不拉取或拉取速度过慢情况下,可能导致信息阻塞;如果kafka没有数据,消费者可能会陷入循环中,一直返回空数据。
Kafka的消费者组是如何消费数据的
(1)一个消费者组有n个消费者
(2)一个消费者组内,一个分区只能由一个消费者消费
(3)一个消费者组,所有消费者组合起来消费一个Topic下所有分区
(4)一个消费者组内,一个消费者可消费多个分区
(5)分区通过分配算法分配给一个组内的消费者,消费者消费时会有一个offset来保存自己的消费位置
Kafka 消费者是否可以消费指定分区消息
Kafa consumer消费消息时,向broker发出fetch请求去消费特定分区的消息,consumer指定消息在日志中的偏移量(offset),就可以消费从这个位置开始的消息,customer拥有了offset的控制权,可以向后回滚去重新消费之前的消息。
Kafka 零拷贝技术
传统数据文件拷贝过程传统的数据文件拷贝过程如下图所示,大概可以分成四个过程:
- 操作系统将数据从磁盘中加载到内核空间的Read Buffer(页缓存区)中。
- 应用程序将Read Buffer中的数据拷贝到应用空间的应用缓冲区中。
- 应用程序将应用缓冲区的数据拷贝到内核的Socket Buffer中。
- 操作系统将数据从Socket Buffer中发送到网卡,通过网卡发送给数据接收方。
通过上图可以发现,传统的数据文件传输需要多次在用户态和核心态之间进行切换,并且需要把数据在用户太和和核心态之间拷贝多次,最终才打到网卡,传输给接收方。
所谓的零拷贝是指将数据在内核空间直接从磁盘文件复制到网卡中,而不需要经由用户态的应用程序之手。这样既可以提高数据读取的性能,也能减少核心态和用户态之间的上下文切换,提高数据传输效率。
- 操作系统将数据从磁盘中加载到内核空间的Read Buffer(页缓存区)中。
- 操作系统直接将数据从内核空间的Read Buffer(页缓存区)传输到网卡中,并通过网卡将数据发送给接收方。
- 操作系统将数据的描述符拷贝到Socket Buffer中。Socket 缓存中仅仅会拷贝一个描述符过去,不会拷贝数据到 Socket 缓存。
Kafka数据零拷贝的过程如下图所示:
通过零拷贝技术,就不需要把内核空间页缓存里的数据拷贝到应用层缓存,再从应用层缓存拷贝到 Socket 缓存了,两次拷贝都省略了,所以叫做零拷贝。这个过程大大的提升了数据消费时读取文件数据的性能。Kafka 从磁盘读数据的时候,会先看看内核空间的页缓存中是否有,如果有的话,直接通过网关发送出去。
Kafka在生产者和消费者两个阶段都使用了零拷贝技术。
kafka服务器默认能接收的最大消息是多少
1M
Kafka新建的分区会在哪个目录下创建
在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。
如果 log.dirs 参数只配置了一个目录,那么分配到各个 Broker 上的分区肯定只能在这个目录下创建文件夹用于存放数据。
如果 log.dirs 参数配置了多个目录,Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区ID。
数据传输的事务有几种
数据传输的事务定义通常有以下三种级别:
- 最多一次(At Most Once):消息不会被重复发送,最多被传输一次,但也有可能一次不传输
- 最少一次(At Least Once ):消息不会被漏发送,最少被传输一次,但也有可能被重复传输
- 精确的一次(Exactly once):不会漏传输也不会重复传输,每个消息都传输被接收
Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?
- 拦截器:用来在消息发送前做一些准备工作,如过滤,修改,定制化。
- 序列化器:将key和value序列化成字节数组,以便进行网络传输。
- 分区器:如果制定了partition字段,就不需要分区器作用;默认调用两个方法,partition(~)方法,参数分别表示主题、键、序列化后的键、值、序列化后的值以及集群的元数据信息,返回值为分区号;close()方法,关闭分区器并回收一些资源。
拦截器 ---> 序列化器 ---> 分区器
Kafka生产者客户端的整体结构是什么样子的?使用了几个线程来处理?分别是什么?
在消息发送的过程中,涉及到了两个线程------ main线程
和 Sender线程
,以及一个线程共享变量------RecordAccumulator
。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker。
"消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据"这句话是否正确?
正确。
失效副本是指什么?有那些应对措施?
不能及时与leader同步,暂时踢出ISR,等其追上leader之后再重新加入
kafka 有几种数据保留的策略?
kafka 有两种数据保存策略:基于过期时间和基于存储的消息大小。
聊一聊Kafka Controller的作用?
Kafka 集群中有一个 broker 会被选举为 Controller,负责管理集群 broker 的上下线 ,所有 topic 的分区副本分配 和 leader 选举等工作。
Controller的信息同步工作是依赖于Zookeeper的。
如果我指定了一个offset,Kafka Controller 怎么查找到对应的消息?
简述Kafka的日志目录结构?
每个分区对应一个文件夹,该文件夹的命名规则为:topic名称+分区序号
。Kafka 采取了 分片 和 索引 机制,将每个 partition 分为多个 segment。每个segment 对应两个文件------.index
文件和.log
文件。
kafka中的 zookeeper 起到什么作用,可以不用zookeeper么
(1)记录有哪些 broker 服务器
(2)记录谁是 leader 以及哪些服务器可用
(3)选举 controller,Kafka 集群中有一个 broker 会被选举为 Controller,负责管
理集群 broker 的上下线,所有 topic 的分区副本分配和 leader 选举等工作
(4)记录消费数据的 offset,在消费者消费数据的时候,需要定时的将分区消息
的消费进度 offset 记录到 zookeeper 中(kafka0.9 版本之前)
kafka 不能脱离 zookeeper 单独使用,因为 kafka 使用 zookeeper 管理和协调 kafka 的节点服务器。
Kafka消费者如何消费多分区
一个 Kafka 消费者可以消费多个分区,可以通过订阅多个分区实现。在创建 Kafka 消费者时,可以通过 subscribe 方法订阅一个主题的多个分区,也可以通过 assign 方法直接分配多个分区给消费者。
通过 subscribe 方法订阅主题时,Kafka 会自动为消费者分配分区,并且在分区发生变化时自动重新分配。如果需要手动分配分区,则可以使用 assign 方法。
Raft
在Kafka 3的新的版本当中,使用了新的KRaft协议,可以不用再依赖于Zookeeper来保存Kafka当中的元数据,转而使用Kafka Raft来实现元数据的一致性,并且将元数据保存在Kafka自己的服务器当中,大大提高了Kafka的元数据管理的性能。