Kafka详解及常见面试问题解析(值得珍藏)

1. 定义

Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。它是一种高吞吐量的分布式发布订阅消息系统,可以处理消费者在网站中的所有动作流数据。这种动作(网页浏览,搜索和其他用户的行动)是在现代网络上的许多社会功能的一个关键因素。这些数据通常是由于吞吐量的要求而通过处理日志和日志聚合来解决。对于像Hadoop一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka的目的是通过Hadoop的并行加载机制来统一线上和离线的消息处理,也是为了通过集群来提供实时的消息。

1.1 消息队列

Kafka 本质上是一个 MQ(Message Queue),使用消息队列的好处?

1.解耦:允许我们独立的扩展或修改队列两边的处理过程。

2.可恢复性:即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

3.缓冲:有助于解决生产消息和消费消息的处理速度不一致的情况。

4.灵活性&峰值处理能力:不会因为突发的超负荷的请求而完全崩溃,消息队列能够使关键组件顶住突发的访问压力。

5.异步通信:消息队列允许用户把消息放入队列但不立即处理它。

1.2 发布/订阅模式

一对多,生产者将消息发布到 topic 中,有多个消费者订阅该主题,发布到 topic 的消息会被所有订阅者消费,被消费的数据不会立即从 topic 清除。

2. 架构

Kafka 存储的消息来自任意多被称为 Producer 生产者的进程。数据从而可以被发布到不同的 Topic 主题下的不同 Partition 分区。在一个分区内,这些消息被索引并连同时间戳存储在一起。其它被称为 Consumer 消费者的进程可以从分区订阅消息。Kafka 运行在一个由一台或多台服务器组成的集群上,并且分区可以跨集群结点分布。

下面给出 Kafka 一些重要概念,让大家对 Kafka 有个整体的认识和感知,后面还会详细的解析每一个概念的作用以及更深入的原理。

Producer: 消息生产者,向 Kafka Broker 发消息的客户端。

Consumer: 消息消费者,从 Kafka Broker 取消息的客户端。

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

Broker: 一台 Kafka 机器就是一个 broker。一个集群由多个 broker 组成。一个 broker 可以容纳多个 topic。

Topic: 可以理解为一个队列,topic 将消息分类,生产者和消费者面向的是同一个 topic。

Partition: 为了实现扩展性,提高并发能力,一个非常大的 topic 可以分布到多个 broker (即服务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个 有序的队列, 可以理解为将标准 MQ 的 Queue 的消息进行拆分, 来实现高可用

Producer 发送的 Message, 根据 key 和 partition 数进行 hash, 然后进行投递,一个分区只能被同一个 Consumer Group 中的一个 Consumer 消费. 分区内消费有序 。

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

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

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

offset: 消费者消费的位置信息,监控数据消费到什么位置,当消费者挂掉再重新恢复的时候,可以从消费位置继续消费。

Zookeeper: Kafka 集群能够正常工作,需要依赖于 zookeeper,zookeeper 帮助 Kafka 存储和管理集群信息。

3. 工作流程

Kafka集群将 Record 流存储在称为 topic 的类别中,每个记录由一个键、一个值和一个时间戳组成。Kafka 是一个分布式流平台,这到底是什么意思?

● 发布和订阅记录流,类似于消息队列或企业消息传递系统。

● 以容错的持久方式存储记录流。

● 处理记录流。

Kafka 中消息是以 topic 进行分类的,生产者生产消息,消费者消费消息,面向的都是同一个 topic。

topic 是逻辑上的概念,而 partition 是物理上的概念,每个 partition 对应于一个 log 文件,该 log 文件中存储的就是 Producer 生产的数据。Producer 生产的数据会不断追加到该 log 文件末端,且每条数据都有自己的 offset。消费者组中的每个消费者,都会实时记录自己消费到了哪个 offset,以便出错恢复时,从上次的位置继续消费。

4. 存储机制

由于生产者生产的消息会不断追加到 log 文件末尾,为防止 log 文件过大导致数据定位效率低下,Kafka 采取了分片索引机制,将每个 partition 分为多个 segment,每个 segment 对应两个文件:".index" 索引文件和 ".log" 数据文件。这些文件位于同一文件夹下,该文件夹的命名规则为:topic 名-分区号。例如,first 这个 topic 有三分分区,则其对应的文件夹为 first-0,first-1,first-2。

".index" 文件存储大量的索引信息,".log" 文件存储大量的数据,索引文件中的元数据指向对应数据文件中 message 的物理偏移量。

5. 生产者

5.1 分区策略

5.1.1 分区原因

● 方便在集群中扩展,每个 partition 可以通过调整以适应它所在的机器,而一个 topic 又可以有多个 partition 组成,因此可以以 partition 为单位读写了。

● 可以提高并发,因此可以以 partition 为单位读写了。

5.1.2 分区原则

我们需要将 Producer 发送的数据封装成一个 ProducerRecord 对象。该对象需要指定一些参数:

● topic:string 类型,NotNull

● partition:int 类型,可选

● timestamp:long 类型,可选

● key:string类型,可选

● value:string 类型,可选

● headers:array 类型,Nullable

(1) 指明 partition 的情况下,直接将给定的 value 作为 partition 的值。

(2) 没有指明 partition 但有 key 的情况下,将 key 的 hash 值与分区数取余得到 partition 值。

(3) 既没有 partition 又没有 key 的情况下,第一次调用时随机生成一个整数(后面每次调用都在这个整数上自增),将这个值与可用的分区数取余,得到 partition 值,也就是常说的 round-robin 轮询算法。

5.2 数据可靠性保证

为保证 producer 发送的数据,能可靠地发送到指定的 topic,topic 的每个 partition 收到 producer 发送的数据后,都需要向 producer 发送 ack(acknowledge 确认收到),如果 producer 收到 ack,就会进行下一轮的发送,否则重新发送数据。

5.2.1 副本数据同步策略

(1)何时发送 ack?

确保有 follower 与 leader 同步完成,leader 再发送 ack,这样才能保证 leader 挂掉之后,能在 follower 中选举出新的 leader 而不丢数据。

(2)多少个 follower 同步完成后发送 ack?

全部 follower 同步完成,再发送 ack。

5.2.2 ISR

采用第二种方案,所有 follower 完成同步,producer 才能继续发送数据,设想有一个 follower 因为某种原因出现故障,那 leader 就要一直等到它完成同步。这个问题怎么解决?

leader维护了一个动态的 in-sync replica set(ISR):和 leader 保持同步的 follower 集合。当 ISR 集合中的 follower 完成数据的同步之后,leader 就会给 follower 发送 ack。如果 follower 长时间未向 leader 同步数据,则该 follower 将被踢出 ISR 集合,该时间阈值由 replica.lag.time.max.ms 参数设定。leader 发生故障后,就会从 ISR 中选举出新的 leader。

5.2.3 ack 应答机制

对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等 ISR 中的 follower 全部接受成功。

所以 Kafka 为用户提供了三种可靠性级别,用户根据可靠性和延迟的要求进行权衡,选择以下的配置。

(1)ack 参数配置:

● 0:producer 不等待 broker 的 ack,这提供了最低延迟,broker 一收到数据还没有写入磁盘就已经返回,当 broker 故障时有可能丢失数据。

● 1:producer 等待 broker 的 ack,partition 的 leader 落盘成功后返回 ack,如果在 follower 同步成功之前 leader 故障,那么将会丢失数据。

● -1(all):producer 等待 broker 的 ack,partition 的 leader 和 follower 全部落盘成功后才返回 ack。但是在 broker 发送 ack 时,leader 发生故障,则会造成数据重复。

5.2.4 故障处理细节

LEO:每个副本最大的 offset。

HW:消费者能见到的最大的 offset,ISR 队列中最小的 LEO。

(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 同步数据。

注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。

5.3 Exactly Once 语义

将服务器的 ACK 级别设置为-1,可以保证 producer 到 server 之间不会丢失数据,即 At Least Once 语义。相对的,将服务器 ACK 级别设置为0,可以保证生产者每条消息只会被发送一次,即At Most Once 语义。

At Least Once 可以保证数据不丢失,但是不能保证数据不重复;相对的,At Most Once 可以保证数据不重复,但是不能保证数据不丢失。但是,对于一些非常重要的信息,比如交易数据,下游数据消费者要求数据既不重复也不丢失,即 Exactly Once 语义。

0.11版本的 Kafka,引入了幂等性:producer 不论向 server 发送多少重复数据,server 端都只会持久化一条。即:At Least Once + 幂等性 = Exactly Once

要启用幂等性,只需要将 producer 的参数中 enable.idompotence 设置为 true 即可。开启幂等性的 producer 在初始化时会被分配一个 PID,发往同一 partition 的消息会附带 Sequence Number。而 borker 端会对 <PID,Partition,SeqNumber> 做缓存,当具有相同主键的消息提交时,broker 只会持久化一条。

但是 PID 重启后就会变化,同时不同的 partition 也具有不同主键,所以幂等性无法保证跨分区会话的 Exactly Once。

6. 消费者

6.1 消费方式

consumer 采用 pull(拉取)模式从 broker 中读取数据。

consumer 采用 push(推送)模式,broker 给 consumer 推送消息的速率是由 broker 决定的,很难适应消费速率不同的消费者。它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 consumer 的消费能力以适当的速率消费消息。

pull 模式不足之处是,如果 Kafka 没有数据,消费者可能会陷入循环中,一直返回空数据。因为消费者从 broker 主动拉取数据,需要维护一个长轮询,针对这一点, Kafka 的消费者在消费数据时会传入一个时长参数 timeout,如果当前没有数据可供消费,consumer 会等待一段时间之后再返回,这段时长即为 timeout。

6.2 分区分配策略

一个 consumer group 中有多个 consumer,一个 topic 有多个 partition,所以必然会涉及到 partition 的分配问题,即确定哪个 partition 由哪个 consumer 来消费。

Kafka 有两种分配策略,一个是 RoundRobin,一个是 Range,默认为range,当消费者组内消费者发生变化时,会触发分区分配策略(方法重新分配)。

(1) RoundRobin

RoundRobin 轮询方式将分区所有作为一个整体进行 hash 排序,消费者组内分配分区个数最大差别为1,是按照组来分的,可以解决多个消费者消费数据不均衡的问题。

但是,当消费者组内订阅不同主题时,可能造成消费混乱,如下图所示,consumer0 订阅主题A,consumer1 订阅主题B,将 A、B主题的分区排序后分配给消费者组,TopicB 分区中的数据可能分配到 consumer0 中。

(2)Range

range 方式是按照主题来分的,不会产生轮询方式的消费混乱问题。

但是,如下图所示,consumer0、consumer1 同时订阅了主题A和B,可能造成消息分配不对等问题,当消费者组内订阅的主题越多,分区分配可能越不均衡。

6.3 offset 的维护

由于 consumer 在消费过程中可能会出现断电宕机等故障,consumer 恢复后,需要从故障前的位置继续消费,所以 consumer 需要实时记录自己消费到了哪个 offset,以便故障恢复后继续消费。

Kafka 0.9 版本之前,consumer 默认将 offset 保存在 Zookeeper 中,从 0.9 版本开始,consumer 默认将 offset 保存在 Kafka 一个内置的 topic 中,该 topic 为 __consumer_offsets。

6.4 Rebalance

Rebalance本质上是一种协议,规定了一个Consumer Group下的所有Consumer如何达成一致,来分配订阅Topic的每个分区。比如某个Group下有20个Consumer实例,它订阅了一个具有100个分区的Topic。正常情况下,Kafka平均会为每个Consumer分配5个分区。这个分配的过程就叫Rebalance。

Consumer Group何时进行Rebalance呢?Rebalance的触发条件有3个。

1.组成员数发生变更。比如有新的Consumer实例加入组或者离开组,或是有Consumer实例崩溃被"踢出"组。

2.订阅主题数发生变更。Consumer Group可以使用正则表达式的方式订阅主题,比如consumer.subscribe(Pattern.compile("t.*c")) 就表 明该Group订阅所有以字母t开头、字母c结尾的主 题。在Consumer Group的运行过程中,你新创建了一个满足这样条件的主题,那么该Group就会发生 Rebalance。

3.订阅主题的分区数发生变更。Kafka当前只能允许增加一个主题的分区数。当分区数增加时,就会触发订阅该主题的所有Group开启Rebalance。

Rebalance过程对Consumer Group消费过程有极大的影响。会stop the world,简称 STW。我们知道在 STW 期间,所有应用线程都会停止工作,表现为整个应用程序僵在那边一动不动。Rebalance过程也和这个类似,在Rebalance过程中,所有Consumer实例都会停止消费,等待Rebalance完成。这是Rebalance为人诟病的一个方面。

Coordinator

Group Coordinator 是一个服务, 每个 Broker 在启动的时候都会启动一个该服务,Group

Coordinator 的作用是用来存储 Group 的相关 Meta 信息, 并将对应 Partition 的 Offset 信息记录到 Kafka 内置 Topic(__consumer_offsets)中 Kafka 在0.9之前是基于 Zookeeper 来存储Partition的 offset 信息(consumers/{group}/offsets/{topic}/{partition}), 因为 Zookeeper 并不适用于频繁的写操作, 所以在0.9之后通过内置 Topic 的方式来记录对应 Partition 的 offset

Rebalance 过程分为两步:Join 和 Sync

  1. Join: 顾名思义就是加入组。这一步中, 所有成员都向 Coordinator 发送 JoinGroup 请求, 请求加入消费组. 一旦所有成员都发送了 JoinGroup 请求, Coordinator 会从中选择一个Consumer 担任 Leader 的角色, 并把组成员信息以及订阅信息发给 Consumer Leader ,注意Consumer Leader 和 Coordinator不是一个概念,Consumer Leader负责消费分配方案的制定。

  2. Sync: Consumer Leader 开始分配消费方案, 即哪个 Consumer 负责消费哪些 Topic 的哪些Partition. 一旦完成分配, Leader 会将这个方案封装进 SyncGroup 请求中发给 Coordinator,非 Leader 也会发 SyncGroup 请求, 只是内容为空。Coordinator 接收到分配方案之后会把方案塞进SyncGroup的Response中发给各个Consumer,这样组内的所有成员就都知道自己应该消费哪些分区了。

6.5 数据压缩

数据压缩的一个基本原理是, 重复数据越多压缩效果越好. 因此将整个Batch的数据一起压缩能更大幅度减小数据量, 从而更大程度提高网络传输效率。

Broker接收消息后,并不直接解压缩,而是直接将消息以压缩后的形式持久化到磁盘Consumer接受到压缩后的数据再解压缩。整体来讲: Producer 到 Broker, 副本复制, Broker 到 Consumer 的数据都是压缩后的数据, 保证高效率的传输。

6.6 Page Cache & MMap

利用 MMap 的读写文件也会依赖于 Page Cache, Page Cache 可以单独存在, 但是 MMap 会依赖于 Page Cache. MMap 是将文件映。

6.7 Page Cache

内核会为每个文件单独维护一个page cache, 用户进程对于文件的大多数读写操作会直接作用到page cache上, 内核会选择在适当的时候将page cache中的内容写到磁盘上 (当然我们可以手工fsync控制回写), 这样可以大大减少磁盘的访问次数, 从而提高性能。至于刷盘时机: page cache中的数据会随着内核中flusher线程的调度以及对sync()/fsync()的调用写回到磁盘, 同样也可以通过手动调用写磁盘 。

6.8 MMap (Memory Mapped Files, 内存映射文件)

MMap 是将一个文件或者其它对象映射进内存. Java 支持的零拷贝参考MappedByteBuffer。

正常的写流程:

  1. JVM向OS发出read()系统调用, 触发上下文切换, 从用户态切换到内核态
  2. 从外部存储 (如硬盘)读取文件内容通过直接内存访问(DMA)存入内核地址空间的缓冲区
  3. 将数据从内核缓冲区拷贝到用户空间缓冲区, read()系统调用返回, 并从内核态切换回用户态
  4. JVM向OS发出write()系统调用, 触发上下文切换, 从用户态切换到内核态
  5. 将数据从用户缓冲区拷贝到内核中与目的地Socket关联的缓冲区
  6. 数据最终经由Socket通过DMA传送到硬件(如网卡)缓冲区, write()系统调用返回, 并从内核态切换回用户态。

读取:

​ 用户态切换到内核态, 在内核空间将文件读取到缓冲区, 再从内核区拷贝到用户缓冲区, 最后切换回用户态。

写入:

用户态切换到内核态, 将数据从用户缓冲区拷贝到内核缓冲区, 再由DMA发送到硬件缓冲区, 最后切换回用户态我们发现, 其实用户空间和内核空间的切换一共四次, 文件拷贝四次.

mmap 的写流程

  1. JVM向OS发出sendfile()系统调用
  2. 从外部存储 (如硬盘)读取文件内容通过直接内存访问(DMA)存入内核地址空间的缓冲区
  3. 数据最终经由Socket通过DMA传送到硬件(如网卡)缓冲区, write()系统调用返回, 并从内核态切换回用户态。

通过零拷贝, 我们减少了两次用户空间和内核空间的拷贝和一次内核空间和 Socket 缓冲区的拷贝,总共节省三次拷贝, 并且没有用户态和内核态的转换。

Kafka 的运用

Kafka 写数据的时候, 会直接写到 Page Cache 中, 消费者拉数据时也会经过 Page Cache. 如果Kafka 的写速率和消费速率差不多, 那么整个生产和消费过程是不会经过磁盘 IO. 全部都是内存操作. 对于 Page Cache 没有刷盘导致的数据丢失, 如果发送方配置消息至少有一个副本接受, 那么也只会有一次同步刷盘。

Kafka为什么不自己管理缓存, 而非要用page cache?

  1. JVM中一切皆对象, 数据的对象存储会带来所谓 object overhead 浪费空间
  2. 如果由JVM来管理缓存, 会受到GC的影响, 并且过大的堆也会拖累GC的效率, 降低吞吐量
  3. 一旦程序崩溃, 自己管理的缓存数据会全部丢失。

7. 面试问题

7.1 数据传输的事物定义有哪三种

数据传输的事务定义通常有以下三种级别:

(1)最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输

(2)最少一次: 消息不会被漏发送,最少被传输一次,但也有可能被重复传输.

(3)精确的一次(Exactly once): 不会漏传输也不会重复传输,每个消息都传输被一次而且仅仅被传输一次,这是大家所期望的 。

7.2 Kafka判断一个节点是否还活着有那两个条件?

(1)节点必须可以维护和ZooKeeper的连接,Zookeeper通过心跳机制检查每个节点的连接

(2)如果节点是个follower,他必须能及时的同步leader的写操作,延时不能太久 。

7.3 producer是否直接将数据发送到broker的leader(主节点)?

producer直接将数据发送到broker的leader(主节点),不需要在多个节点进行分发,为了帮助producer做到这点,所有的Kafka节点都可以及时的告知:哪些节点是活动的,目标topic目标分区的leader在哪。这样producer就可以直接将消息发送到目的地了。

7.4 Kafka consumer是否可以消费指定分区消息?

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

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

Kafka最初考虑的问题是,customer应该从brokes拉取消息还是brokers将消息推送到consumer,也就是pull还push。在这方面,Kafka遵循了一种大部分消息系统共同的传统的

设计:producer将消息推送到broker,consumer从broker拉取消息,一些消息系统比如Scribe和Apache Flume采用了push模式,将消息推送到下游的consumer。这样做有好处也有坏处:由broker决定消息推送的速率,对于不同消费速率的consumer就不太好处理了。

消息系统都致力于让consumer以最大的速率最快速的消费消息,但不幸的是,push模式下,当broker推送的速率远大于consumer消费的速率时,consumer恐怕就要崩溃了。最终Kafka还是选取了传统的pull模式,Pull模式的另外一个好处是consumer可以自主决定是否批量的从broker拉取数据。

Push模式必须在不知道下游consumer消费能力和消费策略的情况下决定是立即推送每条消息还是缓存之后批量推送。如果为了避免consumer崩溃而采用较低的推送速率,将可能导致一次只推送较少的消息而造成浪费。

Pull模式下,consumer就可以根据自己的消费能力去决 定这些策略 Pull有个缺点是,如果broker没有可供消费的消息,将导致consumer不断在循环中轮询,直到新消息到t达。为了避免这点,Kafka有个参数可以让consumer阻塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发.。

7.6 Kafka存储在硬盘上的消息格式是什么?

消息由一个固定长度的头部和可变长度的字节数组组成。头部包含了一个版本号和CRC32校验码。

消息长度: 4 bytes (value: 1+4+n)

版本号: 1 byte

CRC校验码: 4 bytes

具体的消息: n bytes

7.7 Kafka高效文件存储设计特点

(1).Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。

(2).通过索引信息可以快速定位message和确定response的最大大小。

(3).通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。

(4).通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。

7.8 Kaϐka与传统消息系统之间有三个关键区别

(1).Kaϐka 持久化日志,这些日志可以被重复读取和无限期保留

(2)Kaϐka 是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过复制数据提升容错能力和高可用性

(3).Kaϐka 支持实时的流式处理

7.9 Kaϐka创建Topic时如何将分区放置到不同的Broker中

1、副本因子不能大于 Broker 的个数;

2、第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的;

3、其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推; 剩余的副本相对于第一个副本放置位置其实是由nextReplicaShift 决定的,而这个数也是随机产生的。

7.10 Kaϐka新建的分区会在哪个目录下创建

在启动 Kaϐka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kaϐka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。 当然我们也可以配置 log.dir 参数,含义一样。只需要设置其中一个即可。 如果 log.dirs 参数只配置了一个目录,那么分配到各个 Broker 上的分区肯定只能在这个目录下创建文件夹用于存放数据。 但是如果 log.dirs 参数配置了多个目录,那么 Kaϐka 会在哪个文件夹中创建分区目录呢?答案是:Kaϐka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。

7.11 partition的数据如何保存到硬盘

topic中的多个partition以文件夹的形式保存到broker,每个分区序号从0递增, 且消息有序。Partition文件下有多个segment(xxx.index,xxx.log) segment 文件里的 大小和配置文件大小一致可以根据要求修改,默认为1g,如果大小大于1g时,会滚动一个新的segment并且以上一个segment最后一条消息的偏移量命名。

7.12 kaϐka的ack机制

request.required.acks有三个值 0、1、-1。

0: 生产者不会等待broker的ack,这个延迟最低但是存储的保证最弱,当server挂掉的时候就会丢数据。

1:服务端会等待ack值,partition 的 leader 落盘成功后返回 ack,如果在 follower 同步成功之前 leader 故障,那么将会丢失数据。

-1:同样在1的基础上 服务端会等所有的follower的副本受到数据后才会受到leader发出的ack,这样数据不会丢失。

7.13 Kaϐka的消费者如何消费数据

消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置 等到下次消费时,他会接着上次位置继续消费。

7.14 消费者负载均衡策略

一个消费者组中的一个分片对应一个消费者成员,他能保证每个消费者成员都能访问,如果组中成员太多会有空闲的成员。

7.15 数据有序

一个消费者组里它的内部是有序的 消费者组与消费者组之间是无序的 。

7.16 kafaka生产数据时数据的分组策略

1。

0: 生产者不会等待broker的ack,这个延迟最低但是存储的保证最弱,当server挂掉的时候就会丢数据。

1:服务端会等待ack值,partition 的 leader 落盘成功后返回 ack,如果在 follower 同步成功之前 leader 故障,那么将会丢失数据。

-1:同样在1的基础上 服务端会等所有的follower的副本受到数据后才会受到leader发出的ack,这样数据不会丢失。

7.13 Kaϐka的消费者如何消费数据

消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置 等到下次消费时,他会接着上次位置继续消费。

7.14 消费者负载均衡策略

一个消费者组中的一个分片对应一个消费者成员,他能保证每个消费者成员都能访问,如果组中成员太多会有空闲的成员。

7.15 数据有序

一个消费者组里它的内部是有序的 消费者组与消费者组之间是无序的 。

7.16 kafaka生产数据时数据的分组策略

生产者决定数据产生到集群的哪个partition中,每一条消息都是以(key,value)格式 ,Key是由生产者发送数据传入,所以生产者(key)决定了数据产生到集群的哪个partition 。

相关推荐
程序员小潘34 分钟前
Dubbo分布式日志跟踪实现
分布式·dubbo
Z y..44 分钟前
记:Docker部署kafka消费者注册不到问题
docker·容器·kafka
喔喔咿哈哈1 小时前
【手撕 Spring】 -- Bean 的创建以及获取
java·后端·spring·面试·开源·github
理想不理想v2 小时前
使用JS实现文件流转换excel?
java·前端·javascript·css·vue.js·spring·面试
CodingBrother3 小时前
Kafka简单实践
分布式·kafka
不太灵光的程序员4 小时前
【HBase分布式数据库】第七章 数据的导入导出 importtsv导入数据
数据库·分布式·hbase
Xiao Fei Xiangζั͡ޓއއ4 小时前
一觉睡醒,全世界计算机水平下降100倍,而我却精通C语言——scanf函数
c语言·开发语言·笔记·程序人生·面试·蓝桥杯·学习方法
NMBG225 小时前
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
java·开发语言·面试·java-ee·intellij-idea
Acrel_WPP5 小时前
分布式光伏智慧平台建设现场 系统集成商如何盈利
分布式
大山同学5 小时前
DPGO:异步和并行分布式位姿图优化 2020 RA-L best paper
人工智能·分布式·语言模型·去中心化·slam·感知定位