在面试的时候,发现不少面试官特别爱问Kafka相关的问题,这也不难理解,谁让Kafka是大数据领域中消息队列的惟一王者,单机十万级别的吞吐量,毫秒级别的延迟,这种天生的分布式消息队列,谁能不爱?
程序员
在最近的一场面试中,有个面试官看到简历中的项目上写Kafka了,就直接开问Kafka,其余问题基本没问。下面来看下面试官的Kafka八连问:面试
(如下答案是面试完以后整理而成,实际面试时只回答了大约三分之一)redis
缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间能够起到一个缓冲的做用,把消息暂存在kafka中,下游服务就能够按照本身的节奏进行慢慢处理。编程
解耦和扩展性:项目开始的时候,并不能肯定具体需求。消息队列能够做为一个接口层,解耦重要的业务流程。只须要遵照约定,针对数据编程便可获取扩展能力。安全
冗余:能够采用一对多的方式,一个生产者发布消息,能够被多个订阅topic的服务消费到,供多个毫无关联的业务使用。网络
健壮性:消息队列能够堆积请求,因此消费端业务即便短期死掉,也不会影响主要业务的正常进行。app
异步通讯:不少时候,用户不想也不须要当即处理消息。消息队列提供了异步处理机制,容许用户把一个消息放入队列,但并不当即处理它。想向队列中放入多少消息就放多少,而后在须要的时候再去处理它们。异步
kafka消费消息的offset是定义在zookeeper中的, 若是想重复消费kafka的消息,能够在redis中本身记录offset的checkpoint点(n个),当想重复消费消息时,经过读取redis中的checkpoint点进行zookeeper的offset重设,这样就能够达到重复消费消息的目的了分布式
kafka使用的是磁盘存储。ide
速度快是由于:
注:
- Kafka解决查询效率的手段之一是将数据文件分段,好比有100条Message,它们的offset是从0到99。假设将数据文件分红5段,第一段为0-19,第二段为20-39,以此类推,每段放在一个单独的数据文件里面,数据文件以该段中 小的offset命名。这样在查找指定offset的
Message的时候,用二分查找就能够定位到该Message在哪一个段中。- 为数据文件建 索引数据文件分段 使得能够在一个较小的数据文件中查找对应offset的Message 了,可是这依然须要顺序扫描才能找到对应offset的Message。
为了进一步提升查找的效率,Kafka为每一个分段后的数据文件创建了索引文件,文件名与数据文件的名字是同样的,只是文件扩展名为.index。
分三个点说,一个是生产者端,一个消费者端,一个broker端。
kafka的ack机制:在kafka发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的可以被收到,其中状态有0,1,-1。
若是是同步模式:
ack设置为0,风险很大,通常不建议设置为0。即便设置为1,也会随着leader宕机丢失数据。因此若是要严格保证生产端数据不丢失,可设置为-1。
若是是异步模式:
也会考虑ack的状态,除此以外,异步模式下的有个buffer,经过buffer来进行控制数据的发送,有两个值来进行控制,时间阈值与消息的数量阈值,若是buffer满了数据尚未发送出去,有个选项是配置是否当即清空buffer。能够设置为-1,永久阻塞,也就数据再也不生产。异步模式下,即便设置为-1。也可能由于程序员的不科学操做,操做数据丢失,好比kill -9,但这是特别的例外状况。
注:
ack=0:producer不等待broker同步完成的确认,继续发送下一条(批)信息。
ack=1(默认):producer要等待leader成功收到数据并获得确认,才发送下一条message。
ack=-1:producer获得follwer确认,才发送下一条数据。
经过offset commit 来保证数据的不丢失,kafka本身记录了每次消费的offset数值,下次继续消费的时候,会接着上次的offset进行消费。
而offset的信息在kafka0.8版本以前保存在zookeeper中,在0.8版本以后保存到topic中,即便消费者在运行过程当中挂掉了,再次启动的时候会找到offset的值,找到以前消费消息的位置,接着消费,因为 offset 的信息写入的时候并非每条消息消费完成后都写入的,因此这种状况有可能会形成重复消费,可是不会丢失消息。
惟一例外的状况是,咱们在程序中给本来作不一样功能的两个consumer组设置
KafkaSpoutConfig.bulider.setGroupid的时候设置成了同样的groupid,这种状况会致使这两个组共享同一份数据,就会产生组A消费partition1,partition2中的消息,组B消费partition3的消息,这样每一个组消费的消息都会丢失,都是不完整的。 为了保证每一个组都独享一份消息数据,groupid必定不要重复才行。
每一个broker中的partition咱们通常都会设置有replication(副本)的个数,生产者写入的时候首先根据分发策略(有partition按partition,有key按key,都没有轮询)写入到leader中,follower(副本)再跟leader同步数据,这样有了备份,也能够保证消息数据的不丢失。
采集层 主要可使用Flume, Kafka等技术。
Flume:Flume 是管道流方式,提供了不少的默认实现,让用户经过参数部署,及扩展API.
Kafka:Kafka是一个可持久化的分布式的消息队列。 Kafka 是一个很是通用的系统。你能够有许多生产者和不少的消费者共享多个主题Topics。
相比之下,Flume是一个专用工具被设计为旨在往HDFS,HBase发送数据。它对HDFS有特殊的优化,而且集成了Hadoop的安全特性。
因此,Cloudera 建议若是数据被多个系统消费的话,使用kafka;若是数据被设计给Hadoop使用,使用Flume。
kafka 宕机了,首先咱们考虑的问题应该是所提供的服务是否由于宕机的机器而受到影响,若是服务提供没问题,若是实现作好了集群的容灾机制,那么这块就不用担忧了。
想要恢复集群的节点,主要的步骤就是经过日志分析来查看节点宕机的缘由,从而解决,从新恢复节点。
在 Kafka 中,生产者写入消息、消费者读取消息的操做都是与 leader 副本进行交互的,从 而实现的是一种主写主读的生产消费模型。
Kafka 并不支持主写从读,由于主写从读有 2 个很明显的缺点:
数据一致性问题:数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间 窗口会致使主从节点之间的数据不一致。某一时刻,在主节点和从节点中 A 数据的值都为 X, 以后将主节点中 A 的值修改成 Y,那么在这个变动通知到从节点以前,应用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不一致的问题。
延时问题:相似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程须要经历 网络→主节点内存→网络→从节点内存 这几个阶段,整个过程会耗费必定的时间。而在 Kafka 中,主从同步会比 Redis 更加耗时,它须要经历 网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘 这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。
而kafka的主写主读的优势就不少了: