The server is down, will Kafka messages be lost?

Hello everyone, I'm Brother Shu.

The message queue can be described as a necessary middleware under high concurrency, and Kafka, as the leader among them, is often used by us in various scenarios. With Kafka, there are three more problems: message loss, message duplication, and message order. Today, Brother Shu takes you to talk about the problem of message loss.

Article Mind Map

reliability level

Back to the question posed by the title: can we really guarantee that Kafka messages are not lost?

The answer is: we cannot guarantee that Kafka messages will not be lost, only to a certain extent, messages will not be lost.

Some of the situations mentioned here are in order of severity: Kafka downtime, server downtime, computer room earthquake, city destruction, and earth destruction. Don't think Brother Shu is alarmist. If your server is deployed in the capital of Ukraine, will it risk the destruction of the city? Therefore, we set a reasonable reliability level according to the importance of the business. After all, the higher the reliability level, the higher the cost.

If your application is a financial type or a national-level application, then you need to consider the reliability level above the earthquake in the computer room, otherwise it is generally enough to consider the dimension of server downtime. For the earthquake level of the computer room or above, most of them need to do more work in different places, and then do a real-time synchronization of the data of the computer rooms in various places. Even if the Earth is destroyed, and you deploy a computer room on Mars, the principle is similar.

I think the application reliability of most students may only need to consider the level of server downtime, so subsequent considerations are limited to this level.

Looking at Kafka in the Big Picture

To keep Kafka messages from being lost, we must know where Kafka may lose data, so it is very important to understand the entire process of Kafka message flow. For Kafka, its overall architecture can be divided into three parts: producer, Kafka server, and consumer. Its overall architecture is shown in the following figure.

Kafka message architecture diagram

producer

对生产者来说,其发送消息到 Kafka 服务器的过程可能会发生网络波动,导致消息丢失。对于这一个可能存在的风险,我们可以通过合理设置 Kafka 客户端的 request.required.acks 参数来避免消息丢失。该参数表示生产者需要接收来自服务端的 ack 确认,当收不到确认或者超市时,便会抛出异常,从而让生产者可以进一步进行处理。

该参数可以设置不同级别的可靠性,从而满足不同业务的需求,其参数设置及含义如下所示:

  • request.required.acks = 0 表示 Producer 不等待来自 Leader 的 ACK 确认,直接发送下一条消息。在这种情况下,如果 Leader 分片所在服务器发生宕机,那么这些已经发送的数据会丢失。
  • request.required.acks = 1 表示 Producer 等待来自 Leader 的 ACK 确认,当收到确认后才发送下一条消息。在这种情况下,消息一定会被写入到 Leader 服务器,但并不保证 Follow 节点已经同步完成。所以如果在消息已经被写入 Leader 分片,但是还未同步到 Follower 节点,此时Leader 分片所在服务器宕机了,那么这条消息也就丢失了,无法被消费到。
  • request.required.acks = -1 表示 Producer 等待来自 Leader 和所有 Follower 的 ACK 确认之后,才发送下一条消息。在这种情况下,除非 Leader 节点和所有 Follower 节点都宕机了,否则不会发生消息的丢失。

如上所示,如果业务对可靠性要求很高,那么可以将 request.required.acks 参数设置为 -1,这样就不会在生产者阶段发生消息丢失的问题。

Kafka 服务器

当 Kafka 服务器接收到消息后,其并不直接写入磁盘,而是先写入内存中。随后,Kafka 服务端会根据不同设置参数,选择不同的刷盘过程,这里有两个参数控制着这个刷盘过程:

# 数据达到多少条就将消息刷到磁盘
#log.flush.interval.messages=10000
# 多久将累积的消息刷到磁盘,任何一个达到指定值就触发写入
#log.flush.interval.ms=1000

如果我们设置 log.flush.interval.messages=1,那么每次来一条消息,就会刷一次磁盘。通过这种方式,就可以降低消息丢失的概率,这种情况我们称之为同步刷盘。 反之,我们称之为异步刷盘。与此同时,Kafka 服务器也会进行副本的复制,该 Partition 的 Follower 会从 Leader 节点拉取数据进行保存。然后将数据存储到 Partition 的 Follower 节点中。

对于 Kafka 服务端来说,其会根据生产者所设置的 request.required.acks 参数,选择什么时候回复 ack 给生产者。对于 acks 为 0 的情况,表示不等待 Kafka 服务端 Leader 节点的确认。对于 acks 为 1 的情况,表示等待 Kafka 服务端 Leader 节点的确认。对于 acks 为 1 的情况,表示等待 Kafka 服务端 Leader 节点好 Follow 节点的确认。

但要注意的是,Kafka 服务端返回确认之后,仅仅表示该消息已经写入到 Kafka 服务器的 PageCache 中,并不代表其已经写入磁盘了。这时候如果 Kafka 所在服务器断电或宕机,那么消息也是丢失了。而如果只是 Kafka 服务崩溃,那么消息并不会丢失。

因此,对于 Kafka 服务端来说,即使你设置了每次刷 1 条消息,也是有可能发生消息丢失的,只是消息丢失的概率大大降低了。

消费者

对于消费者来说,如果其拉取消息之后自动返回 ack,但消费者服务在处理过程中发生崩溃退出,此时这条消息就相当于丢失了。对于这种情况,一般我们都是采用业务处理完之后,手动提交 ack 的方式来避免消息丢失。

在我们在业务处理完提交 ack 这种情况下,有可能发生消息重复处理的情况,即业务逻辑处理完了,但在提交 ack 的时候发生异常。这要求消费者在处理业务的时候,每一处都需要进行幂等处理,避免重复处理业务。

能不丢失吗?

根据我们上面的分析,Kafka 只能做到 Kafka 应用崩溃这个级别,因为 Kafka 的 acks 仅仅表示写入了 PageCache。

如果服务器宕机了,即使我们设置了每来一条消息就写入一次磁盘,那么也有可能在写入 PageCache 后、写入磁盘前这个关键点,服务器发生宕机。这时候 PageCache 里面的消息数据就没了,那么消息自然也就丢失了。但如果仅仅是 Kafka 应用崩溃退出,因为其已经写入到 PageCache 中了,那么系统自然会将其写入到磁盘中,因此消息并不会丢失。

总结

消息可靠性级别,一定是跟业务重要性关联在一起的。我们无法抛开业务本身的重要性来谈可靠性,只能是取一个平衡的值。

根据我的经验来说,除非是金融类或国民级别的应用,否则只需要考虑到服务器宕机的级别就可以了。而如果是金融级别或国民级别的应用,那么就需要考虑到城市毁灭的可靠性级别。但地球毁灭这个,我想谁也不会去考虑吧。

对于大多数的应用,考虑服务器宕机级别的情况下,对于 Kafka 消息来说,只需要考虑如下几个内容即可:

  1. 生产者。 根据业务重要性,设置好 acks 参数,并做好业务重试,以及告警记录即可。
  2. Kafka 服务端。 根据业务重要性,设置好刷盘参数即可,一般来说都不需要设置成同步刷盘。
  3. consumer. Use the method of manually submitting acks to avoid losing messages, and at the same time, you need to do idempotent processing to avoid repeated processing.

The mind map of this article is shown below.

Article Mind Map

Well, that's it for today's sharing.

If you like today's sharing, remember to support me with one click! Your encouragement is the biggest motivation for me to write articles!


I am participating in the recruitment of the creator signing program of the Nuggets Technology Community, click the link to register and submit .

Guess you like

Origin juejin.im/post/7118947386419839007