在新的遗物中,我们已经建立了管道的一些关键部分Apache Kafka.。这些年来,我们已经成功了大量问题并设计最佳实践管理我们的Kafka集群。我们已经了解了很多关于卡夫卡是如何工作的——既有有效的,也有不那么有效的。

我们遇到的一个基本问题涉及到Kafka的消费者自动提交配置——具体地说,当消费者服务经历了数据丢失或数据复制时如何发生内存(OOM)杀人或者其他类型的硬关机。

让我解释这种行为以及它对Kafka用户意味着什么。

(注意:这篇文章令人熟悉卡夫卡的基本知识,包括生产者和消费者组、主题分区和抵消。)

看看问题

你的生产者发送到Kafka分区的每个消息都有一个抵消-a识别每个消息的顺序索引号。跟踪已经过了哪些消息处理,你的消费者需要提交被处理的消息的偏移量。

在主题分区中承诺的偏移量

除非您手动触发提交,否则您最有可能使用Kafka消费者自动提交机制。自动提交是开箱即用的,默认情况下每5秒提交一次。

对于一个简单的数据转换服务,“处理”意味着,简单地说,一个消息已经进来,被转换,然后产生回Kafka。对于任何其他场景,我们都认为消息未被处理。这很重要,因为如果你消费,但是您的服务在成功生成之前就已经失效了< TransformedMessage >,您不希望提交输入消息的偏移量—您需要让它再次被拾取。

这触及了问题的根源,因为不幸的是,自动提交不是这样工作的。Kafka消费者不知道你对消息做了什么,而且它对提交偏移更加漠不关心。就消费者而言,只要将消息拉入,它就会被“处理”。

所以现在想象一下,您的消费者已从1,000条消息中拉动并将其缓冲到内存中。然后自动提交触发,提交偏移量为这一千次消息。但是,假设您的服务现在使用了太多的内存,并通过OOM kill信号迅速关闭所有消息都被处理。永远不会处理数百条消息。那是数据丢失

主题分区中丢失的事件

相反的情况也是可能的。您可以成功地处理这1000条消息,然后经历一次硬关闭承诺补偿。在这个场景中,您将在另一个实例上重新处理数百条消息消费者重新平衡。那是数据重复

主题分区中的数据复制

好的,那我该怎么办?

坏消息是这里没有任何简单的修复。从根本上讲,这是一致保证较弱的问题。所有Kafka用户想要的是完全一旦处理-保证您只使用和处理一次消息。Kafka版本0.11试图解决这个问题,并使事情略有改善。可以用Kafka 0.11编写一下一旦管道,但要做的一旦消费,您需要在您的消费者中实现自己的事务语义,以便在完成处理时告诉Kafka(或者如果出现问题,请回滚)。

此外,在我们的测试中,我们发现Kafka 0.11中留言生产的交易模型并没有尽快处理消息,因为我们需要高达10 - 100毫秒。这是我们无法承受的额外延迟。

但是,你有一些选择。几个流媒体解决方案,就像亚博直播平台Flink或者卡夫卡流尽可能完全一切地处理,只要您在这些框架的约束范围内。

另一种选择是“滚动您自己的”只执行一次的策略,该策略将只自动提交到达处理管道末端的消息的偏移量。这条建议只适用于最勇敢的人,因为正确处理是相当困难的,而且可能导致的问题比解决的问题还多。

而且总是可以选择接受数据丢失或复制的风险。遗憾的是,这是许多Kafka用户的选择,但这并不总是一个不合理的选择。在这些场景中,实际丢失或重复的数据量相对较小;自动提交应该距离实际最后提交的消息只有几秒钟的时间。(你的整个关卡可能是你看到多少重复或损失的最好指示器)。发生的频率也应该低-理想的Kafka消费者服务没有得到常规的OOM kill信号。

因此,与在您所有的Kafka消费者服务中解决此问题的工程成本相比,如果您使用的数据允许少量的损失,这可能只是您与您居住的风险。当然,您可以通过建立可靠的服务来始终减轻风险。

前进

正如我所说的,我们在New Relic管理Kafka集群有很多经验。我们发现构建高可靠的服务变得越来越困难,因为我们要处理大量的数据量,我们已经做了一些实际的决定,关于如何处理Kafka中的这个特定的缺陷,如果我们的一个服务遭遇硬关闭。

在您接受数据丢失风险的情况下,采取以下步骤以最小化它:

  • 要意识到这个问题,并在风险矩阵中记录它。
  • 确保您的服务稳定。您服务的警报Sigkill.s和Ooms。
  • 在构建新服务时,请考虑使用流系统,该系统可以为您解决此问题。

高级工程师Evan Nelson自2014年以来曾在新的遗物工作。他对建立高吞吐量流系统并解决了与它们的挑战有热情。查看帖子

对新遗物博客的写作有兴趣吗?亚搏体育登入网给我们发一份建议书!