Java高频面试题- 每日三连问?【Day35】 — Kafka篇(三)

2022-04-12 14:23:23 浏览数 (1)

问题导读

一、说说Kafka 如何保证消息的消费顺序?

二、Kafka 如何保证消息不丢失?

三、Kafka 判断一个节点是否还活着有哪两个条件?

01

说说Kafka 如何保证消息的消费顺序?

正经回答:

我们在使用消息队列的过程中经常有业务场景需要严格保证消息的消费顺序,比如我们同时发了 2 个消息,这 2 个消息对应的操作分别对应的数据库操作是:

 更改用户会员等级。

 根据会员等级计算订单价格。

假如这两条消息的消费顺序不一样造成的最终结果就会截然不同。

Kafka 中 Partition(分区)是真正保存消息的地方,我们发送的消息都被放在了这里。

而我们的 Partition(分区) 又存在于 Topic(主题) 这个概念中,并且我们可以给特定 Topic 指定多个 Partition。

每次添加消息到 Partition(分区) 的时候都会采用尾加法,如上图所示。

Kafka 只能为我们保证 Partition(分区) 中的消息有序。

消息在被追加到 Partition(分区)的时候都会分配一个特定的偏移量(offset)。

Kafka 通过偏移量(offset)来保证消息在分区内的顺序性。

所以,我们就有一种很简单的保证消息消费顺序的方法:

1 个 Topic 只对应一个Partition。

这样当然可以解决问题,但是破坏了 Kafka 的设计初衷。

Kafka 中发送 1 条消息的时候,可以指定 topic, partition, key,data(数据) 4 个参数。

如果你发送消息的时候指定了 Partition 的话,所有消息都会被发送到指定的 Partition。

并且,同一个 key 的消息可以保证只发送到同一个 partition,这个我们可以采用表/对象的 id 来作为 key 。

总结一下,对于如何保证 Kafka 中消息消费的顺序,有了下面两种方法:

 1 个 Topic 只对应一个 Partition。

 发送消息的时候指定 key/Partition。

分享朋友圈,记录学习每一天~

02

Kafka 如何保证消息不丢失?

正经回答:

生产者丢失消息的情况

生产者(Producer) 调用 send 方法发送消息之后,消息可能因为网络问题并没有发送过去。

所以,我们不能默认在调用 send 方法发送消息之后消息发送成功了。

为了确定消息是发送成功,我们要判断消息发送的结果。

但是要注意的是 Kafka 生产者(Producer) 使用 send 方法发送消息实际上是异步的操作,我们可以通过 get()方法获取调用结果,但是这样也让它变为了同步操作 。

消费者丢失消息的情况

我们知道消息在被追加到 Partition(分区)的时候都会分配一个特定的偏移量(offset)。

偏移量(offset)表示 Consumer 当前消费到的 Partition(分区)的所在的位置。

Kafka 通过偏移量(offset)可以保证消息在分区内的顺序性。

当消费者拉取到了分区的某个消息之后,消费者会自动提交了 offset。

自动提交的话会有一个问题,试想一下,当消费者刚拿到这个消息准备进行真正消费的时候,突然挂掉了,消息实际上并没有被消费,但是 offset 却被自动提交了。

解决办法也比较粗暴,我们手动关闭自动提交 offset,每次在真正消费完消息之后再自己手动提交 offset 。

但是,细心的朋友一定会发现,这样会带来消息被重新消费的问题。

比如你刚刚消费完消息之后,还没提交 offset,结果自己挂掉了,那么这个消息理论上就会被消费两次。

03

Kafka 判断一个节点是否还活着有哪两个条件?

正经回答:

 节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每个节点的连接;

 如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太久。

- End -

0 人点赞