十家面试,有八家会问的问题:”kafka会不会丢音讯呢”。

有些状况下音讯或许会消失。这或许是因为装备过错或误解Kafka的内部原理所造成的。本文将解释数据丢掉或许发生的状况

Provider(Publisher):承认的时候

当音讯被发送到发布者时,发布者等候来自署理的承认(ACK)。有三个可用的装备选项:

  • acks = all – 当一切副本都承认已保存音讯时,署理才会返回ACK。
  • acks = 1 – 当领导副本保存音讯时返回ACK,但不会等候副本执行相同的操作。
  • acks = 0 – 生产者不会等候来自领导副本的承认。

因为最后一个选项显而易见的是:发送并忘掉,第二个选项或许会导致数据丢掉。在某种状况下,生产者将收到音讯已保存的承认,但leader副本在承认之后宕机了而且无法启动。当新的副本被推举时没有该音讯,所以音讯永久消失了。

JVM中,默许状况下ack设置为1,而在golang中为all。正如您所看到的,不同言语完成存在差异,因而最好显式设置此值。

Provider(Publisher):缓冲区

为了提高性能(或减少网络使用),机器会启用缓冲。当调用发布办法时,音讯不会当即发送,而是在缓冲区到达最大容量或给定的时刻间隔内发送。 这些行为由batch.size(以字节为单位)和linger.ms参数控制。假如到达其间任何一个限制,音讯将当即发送。所以,这需要特别强调:客户端将收到音讯已发送的信息,但这并不是真的。所以,假如应用程序在改写缓冲区之前崩溃,则数据将无法恢复。所以音讯永久消失了。

请注意,这些参数或许因言语完成不同而不同。在JVM中,batch.size是缓冲区中的字节数(默以为16384字节),但在kafka-go中,该参数描述了缓冲区中的音讯数(默以为100)。更重要的是,JVM用户默许将linger.ms设置为0,但kafka-go用户将其设置为1秒。

在JVM完成中,尽管设置linger.ms = 0,音讯仍然可以一起发送。这发生在负载较重的状况下 – 时刻相近的音讯将被批处理。

kafka会丢消息的时刻

Consumer(Subscriber):Offsets

在消费音讯时,顾客(订阅者)将其当前偏移量发送到署理。这是数据丢掉或许发生的地方。

想象一种状况,一个顾客接收了两条音讯:A 和 B。一切音讯都在并行处理。处理音讯时,B 成功了,偏移量被提交。但是,在处理音讯 A 时,呈现了一个过错。因为音讯 B 的偏移量更大,Kafka 将保存最新的偏移量,音讯 A 将永久不会返回给顾客。所以音讯永久消失了。

Broker:已提交并不意味着已保存到磁盘

Kafka 在 Linux 体系上将音讯保存到文件体系缓存(filesystem cache)中,但不会等候音讯持久化到硬盘上。 这意味着假如只要一个副本或 acks=1即使Broker返回了 ACK,Broker也或许崩溃并丢掉音讯。所以音讯永久消失了。

Broker:已保存到硬盘并不意味着它不会消失

leader 与 follower 在数据同步上是有时刻差的。 例如,当一个 follower 署理落后于 leader,但仍被以为是同步的(滞后时刻由 replica.lag.time.max.ms 参数装备,默以为 500),然后 leader 崩溃。新的 leader 被推举出来,但它没有收到音讯。所以音讯永久消失了。

总结

Kafka 是一个具有高容量、一致性和延迟的优异东西。另一方面,许多这些东西取决于生产者、顾客以及broker的装备。

本文列举了几点音讯或许丢掉的场景。所以,面试遇到这个问题,抛出去就好了

本文是我翻译的一篇英文:When you can lose messages in Kafka

初始我用了 ChatGPT翻译了一遍,算是感受了下 ChatGPT 的魅力。准确率80%吧。但别误会,我又人工检验和修改了一遍。

然后我又问了 ChatGPT 一个问题,它也给了我答案。如下图

kafka会丢消息的时刻