Kafka面试题
kafka 都有哪些特点?
高吞吐量,低延迟
可以热扩展
并发度高
具有容错性(挂的只剩1台也能正常跑)
可靠性高
在哪些场景下会选择 kafka? kafka的一些应用
- 日志收集:一个公司可以用kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、HBase、Solr等。
- 消息系统:解耦和生产者和消费者、缓存消息等。
- 用户行为跟踪:kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
- 运营指标:kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
- 作为流式处理的数据源:比如spark streaming和 Flink
kafka 分区的目的?
分区对于kafka集群的好处是:实现负载均衡。
分区对于消费者和生产者来说,可以提高并行度,提高效率。--------提高消费者的并行度---》消费者组
kafka 是如何做到消息的有序性?
kafka中的每个 partition 中的消息在写入时都是有序的(不断追加),而且单独一个 partition只能由一个消费者去消费,可以在里面保证消息的顺序性。但是分区之间的消息是不保证有序的。
kafka 的高可靠性是怎么实现的?
多副本存储
Producer发送数据时可配置ack=all, 并且里面有hw 还有leader-epoch
kafka数据一致性原理
一致性指的是不论在什么情况下,Consumer都能读到一致的数据。
HW 高水位线 在0.11版本之前,只用了高水位线来保证,但是这个里面其实是会出现一些问题的,比如数据丢失,即使是ack等于-1的情况下,也可能会丢数据
LEO等
在0.11版本之后,新加了一个角色叫leader的纪元号,根据高水位线和纪元号来处理,再配上ack=-1的时候,基本上就不会丢数据了。。。。
kafka 在什么情况下会出现消息丢失?
- topic的副本如果只有1个,那么一旦这个副本所在broker服务器宕机,则有可能丢失;
- producer往kafka写入数据时,如果确认机制参数acks !=all,也可能会造成数据丢失;
- 不清洁选举机制如果开启,也可能造成数据丢失(不清洁选举就是说在所有ISR副本全部宕机的情况下,可以让OSR副本成为Leader,而OSR中的数据显然不全;那么,就算之前的Leader重新上线了,也会被进行日志截断)
怎么尽可能保证 kafka 的可靠性
副本数>1
ack=all
min.insync.replicas >= 2
数据传输的语义有几种?
数据传输的语义通常有以下三种级别:
设置消费者里面有enable.auto.commit = true/false
- 最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输
- 最少一次: 消息不会被漏发送,最少被传输一次,但也有可能被重复传输
- 精确一次(Exactly once): 不会漏传输也不会重复传输
kafka 消费者是否可以消费指定分区的消息?
可以,通过assign的方式指定要消费的topic及分区
如果我是subscribe 可以在在均衡监听器的第二个重写方法中使用
kafka 消费者是否从指定偏移量开始消费?
可以,通过seek指定偏移量后再开始消费
客户端操作kafka消息是采用poll模式,还是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不断在循环中轮询,直到新消息到达。为了避免这点,Kafka有个参数可以让consumer阻塞直到新消息到达(当然也可以阻塞直到消息的数量达到某个特定的量这样就可以批量拉取)
kafka 高效文件存储设计特点
Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。 默认存储时间7天
通过索引信息可以快速定位message和确定response的最大大小。
通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小
kafka创建Topic时如何将分区分配给各Broker
- 副本因子不能大于 Broker 的个数;
- 第1个分区(partition_0)的第1个副本放置位置是随机从brokerList选择的;
- 其他分区的第一个副本放置位置相对于partition_0依次往后移。
如果我们有5个 Broker,5个分区,假设第1个分区放在第四个 Broker 上,那么第2个分区将会放在第五个 Broker 上;第3个分区将会放在第一个 Broker 上;第4个分区将会放在第二个 Broker 上,依次类推;
- 各分区剩余的副本相对于第一个副本放置位置由一个随机数nextReplicaShift决定;
kafka的分区分布策略是怎样的?
分区分布的计算策略如下
- 副本因子不能大于 Broker 的个数;
- 第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的;
- 其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第1个分区放在第四个 Broker 上,那么第2个分区将会放在第五个 Broker 上;第3个分区将会放在第一个 Broker 上;第4个分区将会放在第二个 Broker 上,依次类推;
- 剩余副本相对于第1个副本放置位置是由一个随机数nextReplicaShift 决定
kafka分区数可以增加或减少吗?为什么?
kafka允许对topic动态增加分区,但不支持减少分区
Kafka 分区数据不支持减少是由很多原因的,比如减少的分区其数据放到哪里去?是删除,还是保留?删除的话,那么这些没消费的消息不就丢了。如果保留这些消息如何放到其他分区里面?追加到其他分区后面的话那么就破坏了 Kafka 单个分区的有序性。如果要保证删除分区数据插入到其他分区保证有序性,那么实现起来逻辑就会非常复杂。
kafka监控插件都有哪些?
kafka manager
kafka-offset-monitor :主要做消费者偏移量的监控
kafka-eagle:功能很强大!(现已改名为:EFAK —— eagle for apache kafka)
kafka 的消费者组分区分配再均衡
在Kafka中,当有新消费者加入或者订阅的topic数发生变化时,会触发rebalance(再均衡:在同一个消费者组当中,分区的所有权从一个消费者转移到另外一个消费者)机制,Rebalance顾名思义就是重新均衡消费者消费。
Rebalance的过程如下:
- 第一步:所有成员都向coordinator发送请求,请求入组。一旦所有成员都发送了请求,coordinator会从中选择一个consumer担任leader的角色,并把组成员信息以及订阅信息发给leader。
- 第二步:leader开始分配消费方案,指明具体哪个consumer负责消费哪些topic的哪些partition。一旦完成分配,leader会将这个方案发给coordinator。coordinator接收到分配方案之后会把方案发给各个consumer,这样组内的所有成员就都知道自己应该消费哪些分区了。
对于rebalance来说,group coordinator起着至关重要的作用
消费者和消费者组有什么关系?
每个消费者从属于消费组。消费者通过一个参数:group.id 来指定所属的组;
可以把多个消费者的group.id设置成同一个值,那么这几个消费者就属于同一个组;
比如,让c-1,c-2,c-3的group.id=“g1",那么c-1,c-2,c-3这3个消费者都属于g1消费组;
一个消费者,在本质上究竟如何定义:一个消费者可以是一个线程,也可以是一个进程,本质上就是一个consumer对象实例!
消费者组的意义:(可以让多个消费者组成一个组,并共同协作来消费数据,提高消费并行度)一个消费组中的各消费者,在消费一个topic的数据时,互相不重复!如果topic的某分区被组中的一个消费消费,那么,其他消费者就不会再消费这个分区了;
kafka新建的分区会在哪创建存储目录
log.dirs
参数,其值是 kafka 数据的存放目录;
这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性能。
如果log.dirs
参数只配置了一个目录,那么分配到各个 broker 上的分区肯定只能在这个目录下创建文件夹用于存放数据。
但是如果log.dirs
参数配置了多个目录,那么 kafka 会在哪个文件夹中创建分区目录呢?答案是:Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic名+分区ID。
注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。