kafka相关面试题总结

讲讲 kafka 维护消费状态跟踪的方法
大部分消息系统在 broker 端的维护消息被消费的记录:一个消息被分发到
consumer 后 broker 就马上进行标记或者等待 customer 的通知后进行标记。这
样也可以在消息在消费后立马就删除以减少空间占用。
但是这样会不会有什么问题呢?如果一条消息发送出去之后就立即被标记为消费
过的,一旦 consumer 处理消息时失败了(比如程序崩溃)消息就丢失了。为了
解决这个问题,很多消息系统提供了另外一个个功能:当消息被发送出去之后仅
仅被标记为已发送状态,当接到 consumer 已经消费成功的通知后才标记为已被
消费的状态。这虽然解决了消息丢失的问题,但产生了新问题,首先如果 consumer
处理消息成功了但是向 broker 发送响应时失败了,这条消息将被消费两次。第二
个问题时,broker 必须维护每条消息的状态,并且每次都要先锁住消息然后更改
状态然后释放锁。这样麻烦又来了,且不说要维护大量的状态数据,比如如果消
息发送出去但没有收到消费成功的通知,这条消息将一直处于被锁定的状态,
Kafka 采用了不同的策略。Topic 被分成了若干分区,每个分区在同一时间只被一
个 consumer 消费。这意味着每个分区被消费的消息在日志中的位置仅仅是一个
简单的整数:offset。这样就很容易标记每个分区消费状态就很容易了,仅仅需要
一个整数而已。这样消费状态的跟踪就很简单了。
这带来了另外一个好处:consumer 可以把 offset 调成一个较老的值,去重新消
费老的消息。这对传统的消息系统来说看起来有些不可思议,但确实是非常有用
的,谁规定了一条消息只能被消费一次呢?

Kafka 判断一个节点是否还活着有那两个条件?
(1)节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每
个节点的连接
(2)如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太

Kafka 与传统 MQ 消息系统之间有三个关键区别
(1).Kafka 持久化日志,这些日志可以被重复读取和无限期保留
(2).Kafka 是一个分布式系统:它以集群的方式运行,可以灵活伸缩,在内部通过
复制数据提升容错能力和高可用性
(3).Kafka 支持实时的流式处理

kafka 如何不消费重复数据?比如扣款,我们不能重复的扣。

其实还是得结合业务来思考,我这里给几个思路:
比如你拿个数据要写库,你先根据主键查一下,如果这数据都有了,你就别插入
了,update 一下好吧。
比如你是写 Redis,那没问题了,反正每次都是 set,天然幂等性。
比如你不是上面两个场景,那做的稍微复杂一点,你需要让生产者发送每条数据
的时候,里面加一个全局唯一的 id,类似订单 id 之类的东西,然后你这里消费
到了之后,先根据这个 id 去比如 Redis 里查一下,之前消费过吗?如果没有消
费过,你就处理,然后这个 id 写 Redis。如果消费过了,那你就别处理了,保
证别重复处理相同的消息即可。
比如基于数据库的唯一键来保证重复数据不会重复插入多条。因为有唯一键约束
了,重复数据插入只会报错,不会导致数据库中出现脏数据。

kafka 分布式(不是单机)的情况下,如何保证消息的顺序消费?
Kafka 分布式的单位是 partition,同一个 partition 用一个 write ahead log 组织,
所以可以保证 FIFO 的顺序。不同 partition 之间不能保证顺序。但是绝大多数用
户都可以通过 message key 来定义,因为同一个 key 的 message 可以保证只发
送到同一个 partition。
Kafka 中发送 1 条消息的时候,可以指定(topic, partition, key) 3 个参数。
partiton 和 key 是可选的。如果你指定了 partition,那就是所有消息发往同 1
个 partition,就是有序的。并且在消费端,Kafka 保证,1 个 partition 只能被
1 个 consumer 消费。或者你指定 key(比如 order id),具有同 1 个 key 的
所有消息,会发往同 1 个 partition。

你可能感兴趣的:(java面试,java,kafka)