你们好,我是Java最全面试题库
的提裤姐,今天这篇是中间件面试题系列的第三篇,主要总结了Kafka相关的面试题;在后续,会沿着第一篇开篇的知识线路一直总结下去,作到日更!若是我能作到百日百更,但愿你也能够跟着百日百刷,一百天养成一个好习惯。面试
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。
broker 是消息的代理,
Producers往Brokers里面的指定Topic中写消息,Consumers从Brokers里面拉取指定Topic的消息,而后进行业务处理,broker在中间起到一个代理保存消息的中转站。网络
zookeeper 是一个分布式的协调组件,早期版本的kafka用zk作meta信息存储
,consumer的消费状态
,group的管理
以及 offset
的值。
考虑到zk自己的一些因素以及整个架构较大几率存在单点问题,新版本中逐渐弱化了zookeeper的做用。新的consumer使用了kafka内部的group coordination
协议,也减小了对zookeeper的依赖。多线程
Kafka的复制机制既不是彻底的同步复制,也不是单纯的异步复制。
彻底同步复制要求All Alive Follower
都复制完,这条消息才会被认为commit,这种复制方式极大的影响了吞吐率。
异步复制方式下,Follower异步的从Leader复制数据,数据只要被Leader写入log就被认为已经commit,这种状况下,若是leader挂掉,会丢失数据;
kafka使用ISR
的方式很好的均衡了确保数据不丢失以及吞吐率。Follower能够批量的从Leader复制数据,并且Leader充分利用磁盘顺序读以及send file(zero copy)
机制,这样极大的提升复制性能,内部批量写磁盘,大幅减小了Follower与Leader的消息量差。架构
顺序写
:因为现代的操做系统提供了预读和写技术,磁盘的顺序写大多数状况下比随机写内存还要快。Zero-copy
:零拷技术减小拷贝次数Batching of Messages
:批量量处理。合并小的请求,而后以流的方式进行交互,直顶网络上限。Pull 拉模式
:使用拉模式进行消息的获取消费,与消费端处理能力相符。batch.size
producer
实例partition
数acks=-1
时,若是延迟增大:能够增大 num.replica.fetchers
(follower 同步数据的线程数)来调解;socket
缓冲区设置以及 OS tcp
缓冲区设置。1
(默认) 数据发送到Kafka后,通过leader成功接收消息的的确认,就算是发送成功了。在这种状况下,若是leader宕机了,则会丢失数据。0
生产者将数据发送出去就无论了,不去等待任何返回。这种状况下数据传输效率最高,可是数据可靠性确是最低的。-1
producer须要等待ISR中的全部follower都确认接收到数据后才算一次发送完成,可靠性最高。当ISR中全部Replica都向Leader发送ACK时,leader才commit,这时候producer才能认为一个请求中的消息都commit了。一个Kafka的Message由一个固定长度的header
和一个变长的消息体body
组成异步
magic
(文件格式)和四个字节的CRC32
(用于判断body消息体是否正常)构成。当magic的值为1的时候,会在magic和crc32之间多一个字节的数据:attributes
(保存一些相关属性,
好比是否压缩、压缩格式等等);若是magic的值为0,那么不存在attributes属性socket
key/value
消息一样是逻辑上的概念,是Kafka实现单播和广播两种消息模型的手段。
同一个topic的数据,会广播给不一样的group;
同一个group中的worker,只有一个worker能拿到这个数据。
换句话说,对于同一个topic,每一个group均可以拿到一样的全部数据,可是数据进入group后只能被其中的一个worker消费。group内的worker可使用多线程或多进程来实现,也能够将进程分散在多台机器上,worker的数量一般不超过partition的数量,且两者最好保持整数倍关系,由于Kafka在设计时假定了一个partition只能被一个worker消费(同一group内)。async
消息发送
Kafka消息发送有两种方式:同步(sync)和异步(async),
默认是同步方式,可经过producer.type
属性进行配置。
Kafka经过配置request.required.acks
属性来确认消息的生产tcp
综上所述,有6种消息生产的状况,消息丢失的场景:分布式
消息消费
Kafka消息消费有两个consumer接口,Low-level API
和High-level API
:
若是使用高级接口High-level API,可能存在一个问题就是当消息消费者从集群中把消息取出来、并提交了新的消息offset值后,还没来得及消费就挂掉了,那么下次再消费时以前没消费成功的消息就“诡异”的消失了;
解决办法:
针对消息丢失:同步模式下,确认机制设置为-1,即让消息写入Leader和Follower以后再确认消息发送成功;异步模式下,为防止缓冲区满,能够在配置文件设置不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态;
针对消息重复:将消息的惟一标识保存到外部介质中,每次消费时判断是否处理过便可。
在 Kafka 中,生产者写入消息、消费者读取消息的操做都是与 leader 副本进行交互的,从 而实现的是一种主写主读的生产消费模型。
Kafka 并不支持主写从读,由于主写从读有 2 个很明 显的缺点:
网络→主节点内存→网络→从节点内存
这几个阶段,整个过程会耗费必定的时间。而在 Kafka 中,主从同步会比 Redis 更加耗时,它须要经历网络→主节点内存→主节点磁盘→网络→从节点内存→从节点磁盘
这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。