目录

Kafka面试

一句话介绍一下Kafka

一个高吞吐量、分布式的发布-订阅消息系统。

介绍一下Kafka有什么特性

  1. 允许发布订阅数据
  2. 存储流数据时提供相应的容错机制
  3. 当流数据到达时能及时处理

简单说下Kafka如何保证有序性

只能保证一个分区之内的消息的有序性,并不能保证跨分区消息的有序性。每条消息被追加到相应的分区中,是顺序写磁盘,因此效率非常高,也是 Kafka 高吞吐率的一个重要保证。

关于偏移量offset

任何发布到分区的消息会被直接追加到日志文件的尾部,而每条消息在日志文件中的位置都会对应一个按需递增的偏移量,所以 offset 简单来说就是消息的位置。

简单说说Kafka的应用场景

消息系统或是消息队列中间件是当前处理大数据一个非常重要的组件,用来解决应用耦合异步通信流量控制等等问题,从而构建一个高效灵活、消息同步和异步传输处理、存储转发、可伸缩和最终一致性的稳定系统。

Kafka重复消费的问题

问题描述:

采用 Kafka 读取消息进行处理时,consumer 会重复读取 Kafka 队列中的数据。问题如何分析和解决。

问题原因:

Kafka 的 consumer 消费数据时首先会从 broker 里读取一批消息数据进行处理,处理完成后再提交 offset。而我们项目中的 consumer 消费能力比较低(假设),导致取出的一批数据在 session.timeout.ms 时间内没有处理完成,自动提交 offset 失败,然后 Kafka 会重新分配 partition 给消费者,消费者又重新消费之前的一批数据,又出现了消费超时,所以会造成死循环,一直消费相同的数据(极端情况)。

解决方案:

项目中使用的是 spring-kafka,所以把 Kafka 消费者的配置 enable.auto.commit 设为 false,禁止 Kafka 自动提交 offset,从而使用 spring-kafka 提供的 offset 提交策略。spring-kafka 中的 offset 提交策略可以保证一批消息数据没有完成消费的情况下,也能提交 offset,从而避免了提交失败而导致永远重复消费的问题。

Kafka中的消息是否会丢失和重复消费

From: https://blog.csdn.net/u012050154/article/details/78592854

Spark Streaming+Kafka如何保证数据不丢失、不重复

From: https://blog.csdn.net/enjoy524/article/details/53446893

保证数据不丢失(at-least):

Spark RDD 内部机制可以保证数据 at-least 语义。

  1. Receiver 方式: 开启 WAL(预写日志),将从 Kafka 中接受到的数据写入到日志文件中,所有数据从失败中可恢复。失败了,可以从日志中从新读取。
  2. Direct 方式: 依靠 checkpoint 机制来保证。

保证数据不重复(exactly-once):

要保证数据不重复,即 exactly once 语义。

  1. 幂等操作: 重复执行不会产生问题,不需要做额外的工作即可保证数据不重复。
  2. 业务代码添加事务操作
1
2
3
4
5
6
7
dstream.foreachRDD {(rdd, time) =
  rdd.foreachPartition { partitionIterator =>
    val partitionId = TaskContext.get.partitionId()
    val uniqueId = generateUniqueId(time.milliseconds, partitionId)
    //use this uniqueId to transationally commit the data in partitionIterator
 }
}

就是说针对每个 partition 的数据,产生一个 uniqueId,只有这个 partition 的所有数据被完全消费,则算成功,否则算失效,要回滚。下次重复执行这个 uniqueId 时,如果已经被执行成功,则 skip 掉。

Spark Streaming使用Kafka保证数据零丢失

From: https://github.com/jacksu/utils4s/blob/master/spark-knowledge/md/spark_streaming%E4%BD%BF%E7%94%A8kafka%E4%BF%9D%E8%AF%81%E6%95%B0%E6%8D%AE%E9%9B%B6%E4%B8%A2%E5%A4%B1.md

简单说说Kafka如何消费消息

Kafka 的消费者以 Pull 的方式获取消息,同时 Kafka 采用了消费组的模式,每个消费者都属于某一个消费者组。在创建消费者时,如果不指定消费者的 groupId,则该消费者属于默认消费组

同一个消费组下的各消费者消费消息的时候是互斥的,对于一条消息而言,就同一个消费组的消费者来讲,只能被同组下的某一个消费者消费,但不同消费组的消费者能消费同一条消息,正因如此,我们很方便通过消费组来实现消息的单播和广播

说说新旧版消费者的区别

旧版消费者默认把消费偏移量保存到 ZooKeeper 中,可以同 offset.storage 进行设置,弱 offsets.storage=kafka 则将偏移量保存到 Kafka 内部主题中,若设置 offsets.storage=zookeeper,则将偏移量保存到 ZooKeeper 中。当 offset.storage=kafka 时,还可以通过配置项 dual.commit.enabled=true 设置同时将偏移量保存到 ZooKeeper中。

警告
本文最后更新于 2017年2月1日,文中内容可能已过时,请谨慎参考。