一、Kafka是什么?
Kafka是一个分布式的基于发布/订阅模式的消息队列。分布式消息队列可以看成是将这种先进先出的数据结构独立部署在服务器上,应用程序可以通过远程访问接口使用它。
二、Kafka的工作机制是什么?
1.基本概念
2.消息模型
发布订阅模式:一对多,消费者消费数据之后不会清除消息
一次消息写入多次消费,当然前提是消费者位于不同的消费者组。
3.存储机制
Kafka的消息是存储在磁盘的,所以数据不易丢失。
4.生产流程
1)主线程首先将业务数据封装成ProducerRecord对象
2)调用send方法将消息放入消息收集器RecordAccumlator中暂存
3)Sender线程将消息信息构成请求
4)执行网络IO的线程从RecordAccumlator中将消息取出并批量发送出去
5.消费流程
Kafka消费者从属于消费者组。消费者组内的消费者订阅的是相同主题,每个消费者接收主题的一部分分区的消息。
三、Kafka常见面试题
1.Kafka的多分区多副本机制有什么好处?
1)Kafka通过将特定topic指定到多个partition,各个partition分布到不同的Broker上,这样能够提供比较好的并发能力。
2)Partition可以指定对应的replica数,这也极大地提高了消息存储的安全性和容灾能力。
2.Kafka如何实现高效读写?
1)顺序写入磁盘:在日志文件尾部追加,顺序写入且不允许修改。
2)页缓存:每次从磁盘中加载一页的数据到内存中这样可以减少IO次数。
3)零拷贝技术:只用将磁盘中的数据复制到页面缓存中一次,然后将数据从页面缓存中发送到网络中,避免了重复复制操作。
常规数据交互模式:
零CPU拷贝模式:
splice系统调用可以在内核缓冲区和socket缓冲区之间建立管道来传输数据,避免了两者之间的CPU拷贝操作。
3.为什么消费者用pull模式从broker中读取数据?
pull模式可以根据消费者的能力以适当的消费速率消费消息,避免造成网络拥塞。pull模式的不足之处在于,如果kafka没有数据,消费者会陷入空循环中,针对这一点,Kafka的消费者会在消费时传入timeout参数,如果当前Kafka中没有数据,消费者会等待一个timeout时长再返回。
4.Kafka如何保证消息的顺序消费呢?
1)当partition只有一个时可以做到全局有序,Kafka只能保证分区内部消息消费的有序性。
2)在发送消息时指定key和postion,从而可以保证间隔有序。
5.Kafka如何保证消息不丢失?
1)生产者确认
topic的每个partition收到producer发送的数据后,都需要向producer发送ack,如果producer收到ack,就会进行下一轮发送,否则重新发送数据。
Leader维护了一个动态的ISR(in-sync replica),它是一个保持同步的follower集合。当ISR中的follower完成数据的同步之后,leader就会给follower发送一个ack。如果follower长时间未从leader同步数据,则该follower将被踢出ISR,该时间由阈值replica.lag.max.ms参数设定。Leader发生故障后,ISR将会重新选举新的Leader。
Kafka为用户提供了三种可靠性级别,用户可根据对可靠性和延迟的要求权衡。
ack=0,生产者在成功写入消息之前不会等待任何来自服务器的响应,如果出现问题生产者感知不到,但能够以网络支持的最大速度发送消息。
ack=1,默认值,只要集群的首领节点leader收到消息,生产者就会收到一个来自服务器的成功响应。如果消息无法到达首领节点,生产者会收到一个错误响应,为了避免数据丢失,生产者将重发消息。如果收到写成功通知,但首领节点还没来的及同步follower节点就崩溃了,也会造成数据丢失。
ack=-1,只有当所有所有参与复制的节点收到消息后,生产者会收到一个来自服务器的成功确认。如果在follower同步完成之后,broker返回ack之前,leader发生故障,那么会造成数据重复。
2)消费者确认
一次poll会拉取一批消息,对应的消费位移是一个区间,如果是拉取信息之后进行位移提交,在消费中间中间发生了故障,会造成消息丢失现象。如果是消费完成之后进行位移提交,在消费中间发生了故障,会造成重复消费现象。
将位移提交方式改为手动提交,即每次消费完成之后提交,可以避免因为消费未完成出现异常导致的消息丢失。
6.Kafka如何保证消息不重复消费?
自动提交offset,在下一次提交位移之前消费者崩溃了,那么又会从上一次位移提交的地方重新开始消费,这样便造成了重复消费。
使用异步提交方式,此时可以设置一个递增的序号来维护异步提交的顺序,每次位移提交之后就增加对应的序号值。在遇到位移提交失败需要重试的时候,可以检查所需要提交的位移和序号值的大小,如果前者的值大于后者,则说明有更大的位移已经提交了,不需要进行本次重试;如果前者等于后者,则进行重试。除非编码错误,否则不会出现前者大于后者的情况。
7.broker宕机后如何保证副本间数据的一致性?
1)follower发生故障后,会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步,等该follower大于partition的HW时,即follower追上leader时,就可以重新加入ISR了。
2)leader发生故障后,会从ISR重新选举一个新的leader,为了保证多个副本之间数据的一致性,所有follower会先将各自的log文件高于HW的部分截取掉,重新从新的leader同步数据。
注意,这只能保证副本之间数据的一致性,不能保证数据不丢失或者不重复。
8.Zookeeper在kafka中的作用?
Broker注册:在Zookeeper上有个专门记录broker服务器列表的节点,每个broker启动时,都会在/brokers/ids下创建属于自己的节点,每个broker会将自己的IP地址和端口信息记录到节点上去。
Topic注册:同一个topic的消息会被分成多个分区并分布在多个broker上,这些分区和broker的对应关系也都是Zookeeper在维护,对应到Zookeeper中可能会创建文件/brokers/topics/my-topic/partitions/0,/brokers/topics/my-topic/partitions/1。
负载均衡:为了提供更好的并发能力,Kafka会尽力将同一个topic的partition分布到不同的broker,当Consumer消费的时候,Zookeeper可以根据当前的partition数量和Consumer数量进行动态负载均衡。