第 1 题 Kafka 数据可靠性如何保证?
对于 kafka 来说,以下几个方面来保障消息分发的可靠性:
消息发送的可靠性保障(producer)
消息消费的可靠性保障(consumer)
Kafka 集群的可靠性保障(Broker)
生产者
目前生产者发送消息(acks)有三种方式。
acks=0
producer 不等待 broker 的 acks。发送的消息可能丢失,但永远不会重发。
acks=1
leader 不等待其他 follower 同步完毕,leader 直接写 log,然后发送 acks 给 producer。这种情况下会有数据重发现象,可靠性比 only once 好点,但是仍然会丢消息。例如 leader挂了,但是其他 replication 还没完成同步。
acks=all
leader 等待所有 follower 同步完成才返回 acks。消息可靠不丢失(丢了会重发),没收到ack 会重发。
消费者
如果将 consumer 设置为 autocommit,consumer 一旦读到数据立即自动 commit。如果只讨论这一读取消息的过程,那 Kafka 确保了 Exactly once。
但实际使用中应用程序并非在 consumer 读取完数据就结束了,而是要进行进一步处理,而数据处理与 commit 的顺序在很大程度上决定了 consumer delivery guarantee:
At most once:读完消息先 commit,再处理消息。
如果 consumer 在 commit 后还没来得及处理消息就 crash 了,下次重新开始工作后就无法读到刚刚已提交而未处理的消息,因为此时 offset 已经改变了。
Kafka 集群
对于 broker,落盘的数据,有 replica 机制保证数据不丢失。
对于内存(没有 flush 磁盘)数据,broker 重启会丢失。可以通过 log.flush.interval.messages 和 log.flush.interval.ms 来配置 flush 间隔,如果 interval 设置过大丢的数据多些,设置过小会影响性能。
第 2 题 生产环境中,Kafka 如何保证数据不丢失?
producer.type=sync 或者 async 来设置同步或者异步
1.生产者端
同步模式:确认机制设置为-1(request.required.acks=-1),也就是让消息写入 leader和所有的副本。
异步模式:如果消息发出去了,但还没有收到确认的时候,缓冲池满了,在配置文件中设置成不限制阻塞超时的时间(queue.enqueue.timeout.ms=-1),也就说让生产端一直阻塞,这样也能保证数据不会丢失。
2.消费者端
1) 如果使用 flink消费 kafka,启用 checkpoint 容错机制保证数据不丢失(保存 offset)。
2) 如果使用 flink消费 kafka,业务处理完之后,再手动提交 offset,也可保证数据不丢失。
第 3 题 Kafka 高效文件存储设计特点?
一个 Kafka topic 可以包含多个 partition,一个 partition 大文件可以分成多个 segment文件段,通过多个小文件段就容易定期清除或删除已经消费完文件,减少磁盘占用。
通过跳表可以快速定位到 segment 文件段
通过稀疏索引 Index 可以快速定位 message 消息
稀松索引 Index 可以全部加载到内存,可以避免 segment file 整个文件的 IO 磁盘操作。
通过索引文件稀疏存储,可以大幅降低 index 文件元数据占用空间大小。
第 4 题 Kafka 创建 Topic 时如何将分区放置到不同的 Broker 中?
1)副本因子不能大于 Broker 的个数;
2)第一个分区(编号为 0)的第一个副本放置位置是随机从 brokerList 选择的;
3)其他分区的第一个副本放置位置相对于第 0 个分区依次往后移。也就是如果我们有 5个Broker,5 个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个Broker 上,依次类推。
4)剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的。
第 5 题 Kafka 新建的分区会在哪个目录下创建?
Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区 ID。
注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。
第 6 题 Kafka partition 的数据如何保存到硬盘?
参考答案:
topic 中的多个 partition 以文件夹的形式保存到 broker,每个分区序号从 0 递增,且消息有序
Partition 文件下有多个 segment(xxx.index,xxx.log)。segment 文件里的大小和配置文件大小一致,可以根据要求修改,默认为 1g。如果 segment 大小大于 1g 时,会滚动一个新的 segment 并且以上一个 segment 最后一条消息的偏移量命名。
第 7 题 说一说 kafka 的 ack 机制?
request.required.acks 有三个值:0、 1、 -1。
1)0: 生产者不会等待 broker 的 ack,这个延迟最低但是存储的保证最弱,当 server 挂掉的时候就会丢数据。
2)1:生产者会等待 broker 的 ack, leader 确认接收到消息后发送 ack ,但是如果leader 挂掉后,他不确保 follower 是否复制完成,可能会导致数据丢失。
3)-1:生产者会等待 broker 的 ack, leader 和 follower 都收到消息后才会向生产者发送 ack,这样数据不会丢失。
第 8 题 Kafka 的消费者如何消费数据?
消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置等到下次消费时,他会接着上次位置继续消费。
第 9 题 说一说消费者负载均衡策略?
参考答案:
一个 kafka 分区只能被一个消费者消费,一个消费者可以消费多个 kafka 分区。
当 kafka 分区数跟消费者组中的消费者数量一致,一个消费者对应一个分区。
当 kafka 分区数大于消费者组中的消费者数量,一个消费者对应多个分区。
当 kafka 分区数小于消费者组中的消费者数量,一个消费者对应一个分区,此时消费者会有空闲。
第 10 题 kafka 生产数据时数据的分组策略?
生产者决定数据产生到集群的哪个 partition 中,每一条消息都是以(key,value)格式,Key 是由生产者发送数据传入,所以生产者(key)决定了数据产生到集群的哪个 partition。
第 11 题 为什么要使用消息队列,为什么要使用 kafka?
参考答案:
1)缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka 在中间可以起到一个缓冲的作用,把消息暂存在 kafka 中,下游服务就可以按照自己的节奏进行慢慢处理。
2)解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。
3)冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅 topic 的服务消费到,供多个毫无关联的业务使用。
4)健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正常进行。
5)异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
第 12 题 Kafka 中的 ISR、AR 又代表什么?ISR 的伸缩又指什么?
ISR: In-Sync Replicas 副本同步队列
AR: Assigned Replicas 所有副本
ISR 是 由 leader 维 护 , follower 从 leader 同 步 数 据 有 一 些 延 迟 ( 包 括 延 迟 时 间 replica.lag.time.max.ms 和延迟条数 replica.lag.max.messages两个维度, 当前最新的版本 0.10.x 中只支持 replica.lag.time.max.ms 这个维度),任意一个超过阈值都会把 follower 剔除出 ISR, 存入 OSR(Outof-Sync Replicas)列表,新加入的 follower 也会先存放在OSR 中。AR=ISR+OSR。
第 13 题 kafka follower 如何与 leader 同步数据?
Kafka 的复制机制既不是完全的同步复制,也不是单纯的异步复制。完全同步复制要求 All Alive Follower 都复制完,这条消息才会被认为 commit,这种复制方式极大的影响了吞吐率。而异步复制方式下,Follower 异步的从 Leader 复制数据,数据只要被 Leader 写入 log就被认为已经 commit,这种情况下,如果 leader 挂掉,会丢失数据,kafka 使用 ISR 的方式很好的均衡了确保数据不丢失以及吞吐率。Follower 可以批量的从 Leader 复制数据,而且 Leader 充分利用磁盘顺序读以及 send file(zero copy)机制,这样极大的提高复制性能,内部批量写磁盘,大幅减少了 Follower 与 Leader 的消息量差。
第 14 题 什么情况下一个副本会从 ISR 中踢出去?
leader 会维护一个与其基本保持同步的 Replica 列表,该列表称为 ISR(in-sync Replica),每个 Partition 都会有一个 ISR,而且是由 leader 动态维护 ,如果一个 follower 比一个leader 落后太多,或者超过一定时间未发起数据复制请求,则 leader 将其重 ISR 中移除 。
第 15 题 kafka producer 如何优化写入速度?
1)增加线程
2)提高 batch.size
3)增加更多 producer 实例
4)增加 partition 数
5)producer 参数设置为 acks=0,提高吞吐量,但是消息存在丢失风险。(监控日志可以采用这个)
第 16 题 kafka producer 写数据,ack 的值 0、1、-1 分别代表什么意思, ack 设置 -1 的时候,什么情况下,leader 会认为一条消息 commit 了?
1)1(默认) 数据发送到 Kafka 后,经过 leader 成功接收消息的的确认,就算是发送成功了。在这种情况下,如果 leader 宕机了,则会丢失数据。
2)0 生产者将数据发送出去就不管了,不去等待任何返回。这种情况下数据传输效率最高,但是数据可靠性确是最低的。
3)-1 producer 需要等待 ISR 中的所有 follower 都确认接收到数据后才算一次发送完成,可靠性最高。当 ISR 中所有 Replica 都向 Leader 发送 ACK 时,leader 才 commit,这时候 producer 才能认为一个请求中的消息都 commit 了。
第 17 题 kafka 中 consumer group 是什么?
消费者组,每个 Consumer 属于一个 Consumer Group;反过来,每个 Consumer Group中可以包含多个 Consumer。如果所有的 Consumer 都具有相同的 Consumer Group,那么消息将会在 Consumer 之间进行负载均衡。也就是说一个 Partition 中的消息只会被相同Consumer Group 中的某个 Consumer 消费,每个 Consumer Group 消息消费是相互独立的。
第 18 题 kafka 分布式(不是单机)的情况下,如何保证消息的顺序消费?
Kafka 分布式的单位是 partition,同一个 partition 用一个 write ahead log 组织,所以可以保证 FIFO 的顺序。不同 partition 之间不能保证顺序。但是绝大多数用户都可以通过 message key 来定义,可以自定义分区器让同一个 key 的 message 被发送到同一个 partition。
Kafka 中发送 1 条消息的时候,可以指定(topic, partition, key) 3 个参数。partiton 和key 是可选的。如果你指定了 partition,那就是所有消息发往同 1 个 partition,就是有序的。并且在消费端,Kafka 保证,1 个 partition 只能被 1 个 consumer 消费。或者你指定 key( 比如 order id),通过自定义分区器,具有同 1 个 key 的所有消息,会发往同 1 个 partition。
第 19 题 请简述下你在哪些场景下会选择 Kafka?
日志收集:一个公司可以用 Kafka 可以收集各种服务的 log,通过 kafka 以统一接口服务的方式开放给各种 consumer,例如 hadoop、HBase、Solr 等。
消息系统:解耦和生产者和消费者、缓存消息等。
用户活动跟踪:Kafka 经常被用来记录 web 用户或者 app 用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到 kafka 的 topic 中,然后订阅者通过订阅这些 topic 来做实时的监控分析,或者装载到 hadoop、数据仓库中做离线分析和挖掘。
运营指标:Kafka 也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
流式处理:比如 spark streaming 和 Flink
第 20 题 Kafka 分区的目的?
分区对于 Kafka 集群的好处是:实现负载均衡。
分区对于消费者来说,可以提高并发度,提高效率,达到数据容错。
题 21 题 消费者和消费者组有什么关系?
每个消费者从属于消费组。
第 22 题 Kafka 分区数可以增加或减少吗?为什么?
我们可以使用 bin/kafka-topics.sh 命令对 Kafka 增加 Kafka 的分区数据,但是 Kafka不支持减少分区数。
Kafka 分区数据不支持减少是由很多原因的,比如减少的分区其数据放到哪里去?是删除,还是保留?删除的话,那么这些没消费的消息不就丢了。如果保留这些消息如何放到其他分区里面?追加到其他分区后面的话那么就破坏了 Kafka 单个分区的有序性。如果要保证删除分区数据插入到其他分区保证有序性,那么实现起来逻辑就会非常复杂。
第 23 题 Kafka扩了broker节点之后怎么均衡数据?
第一步:生成迁移计划
先手动生成一个topic.json,内容如下。这里topic可以是一个列表。
{
"topics": [
{"topic": "test0"},{"topic": "test1"},{"topic": "test2"},{"topic": "test3"}
],
"version": 1
}
第二步:执行迁移计划
第三步:检查
第 24 题 Kafka高效读写数据
1)Kafka本身是分布式集群,同时采用分区技术,并发度高。
2)顺序写磁盘
Kafka的producer生产数据,要写入到log文件中,写的过程是一直追加到文件末端,为顺序写。官网有数据表明,同样的磁盘,顺序写能到600M/s,而随机写只有100K/s。
3)零复制技术
第 25 题 Kafak offset保存在哪里?
kafka0.9版本之前,consumer默认将offset保存在zookeeper中,从0.9版本开始,consumer默认将offset保存在kafka一个内置的topic中,该topic为_consumer_offset。
第 26 题 Kafka消息数据积压,Kafka消费能力不足怎么处理?
1)如果是Kafka消费能力不足,则可以考虑增加Topic的分区数,并且同时提升消费组的消费者数量,消费者数 = 分区数。(两者缺一不可)
2)如果是下游的数据处理不及时:提高每批次拉取的数量。批次拉取数据过少(拉取数据/处理时间 < 生产速度),使处理的数据小于生产的数据,也会造成数据积压。
第 27 题 Kakfa分区数
1)创建一个只有1个分区的topic
2)测试这个topic的producer吞吐量和consumer吞吐量。
3)假设他们的值分别是Tp和Tc,单位可以是MB/s。
4)然后假设总的目标吞吐量是Tt,那么分区数=Tt / min(Tp,Tc)
例如:producer吞吐量 = 20m/s;consumer吞吐量 = 50m/s,期望吞吐量100m/s;
分区数 = 100 / 20 = 5分区
分区数一般设置为:3-10个
第 28 题 Kafka单条日志传输大小
Kafka对于消息体的大小默认为单条最大值是1M但是在我们应用场景中,常常会出现一条消息大于1M,如果不对Kafka进行配置。则会出现生产者无法将消息推送到Kafka或消费者无法去消费Kafka里面的数据,这时我们就要对Kafka进行以下配置:server.properties
replica.fetch.max.bytes: 1048576 broker可复制的消息的最大字节数, 默认为1M
message.max.bytes: 1000012 kafka 会接收单个消息size的最大限制, 默认为1M左右
注意:message.max.bytes必须小于等于replica.fetch.max.bytes,否则就会导致replica之间数据同步失败。