用 《异星工厂》游戏形象理解Apache Kafka - Ruurtjan


Factorio异星工场 是一个开放世界的 RTS,您可以在其中构建和优化供应链以发射卫星并恢复与您的家乡星球的通信,而 Kafka 是一个分布式流媒体平台,它处理异步通信一种持久的方式。
我想知道 在 Factorio 和 Kafka 之间的类比开始崩溃之前,我们能走多远。让我们从头开始,通过 Factorio 可视化探索核心 Kafka 概念,并在此过程中获得一些乐趣。

为什么要打扰异步消息传递?
假设我们有三个微服务。一种用于开采铁矿石,一种用于将铁矿石熔炼成铁板,一种用于用这些板生产铁齿轮。我们可以使用同步 HTTP 调用链接这些服务。每当我们的矿机有新的铁矿石时​​,它都会对冶炼炉进行 POST 调用,熔炼炉又会 POST 到工厂。

从左到右:采矿、冶炼和生产——通过同步通信紧密耦合
这种设置对我们很有用,直到工厂停电。熔炉的 HTTP 调用失败,导致矿机的调用也失败。我们可以实现断路器和重试来防止级联故障和消息丢失,但在某些时候我们将不得不停止尝试,否则我们将耗尽内存。

工厂停电
如果只有一种方法可以将这些微服务解耦……当然,这就是 Kafka 的用武之地。使用 Kafka,您可以以容错和持久的方式存储记录流。在 Kafka 术语中,这些流称为主题

通过异步消息解耦的微服务
对于服务、消息或记录之间的异步主题,在峰值负载和中断时会被缓冲。这些缓冲区显然容量有限,所以让我们谈谈可扩展性。
我们可以通过向集群添加 Kafka 服务器来增加存储容量和吞吐量。另一种方法是增加磁盘大小(用于存储)或 CPU 和网络速度(用于吞吐量)。这些选项中的哪一个为您提供了最佳的性价比取决于用例,但购买更大的服务器 - 与购买更多服务器不同- 受制于收益递减规律。Kafka 的容量随着每个节点的增加而线性扩展,所以这通常是要走的路。

垂直扩展——更大、更昂贵的服务器

水平扩展——将负载分布到更多的服务器上
为了在多个服务器之间划分主题,我们需要一种将主题拆分为更小的子流的方法。这些子流称为分区。每当服务产生新记录时,该服务就会决定该记录应位于哪个分区。

一个产生记录的旅行车,一个将消息放在正确分区上的分区器,以及一个具有四个分区的主题。
在 href="https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/clients/producer/internals/DefaultPartitioner.javaL69">默认分区散列消息键和modulos,超过分区的数量:
return Utils.toPositive(Utils.murmur2(keyBytes)) % numPartitions;
这样,具有相同键的消息总是在同一个分区上结束。
请注意,消息只能保证在生产者和分区的上下文中进行排序。来自多个生产者或来自多个分区上的单个生产者的记录可以交错。
 
如何消费?
现在我们知道了消息是如何被放到主题上的,让我们看看它们是如何被消费的。当您开始收听主题时,默认情况下所有分区的记录都会路由给您。但是,同时运行多个微服务实例以实现更高的吞吐量或可用性是很常见的。如果他们都开始收听主题,则每个记录都会被每个实例处理,这通常不是您想要的。

消费者组允许您在多个消费者之间均匀划分分区。当一个微服务实例加入消费者组时,Kafka 会重新分配一些分区给它。同样,当实例崩溃或因其他原因离开组时,其分区将分配给其他实例。Kafka 确保分区始终在每个组中的消费者之间平均分配。

如果某个主题的每个分区的记录数存在偏差,您可能会遇到麻烦。一个实例可能无法跟上,因为它被分配了具有许多记录的分区,而其他实例则处于空闲状态。您需要确保没有分区的记录比其他分区多得多。

每个消费者都会跟踪它已经处理了哪些记录。由于记录是按顺序处理的,一个简单的偏移量就足够了。每隔一段时间(默认为 5 秒),消费者会将其偏移量提交给 Kafka 当一个消费者离开它的组时,它的分区被分配给组中的其他消费者。新消费者将能够从前一个消费者停止的偏移量开始请求记录。记录可能已被处理,但尚未提交。您要么必须从提交的偏移量开始,要么开始处理新消息并跳过尚未处理的所有内容。这就是为什么 Kafka 只能保证消息至少传递一次,或者最多传递一次。
 
最后总结
当我们开始复制数据时,这个类比就不再有意义了。使用 Kafka,我们可以多次处理单个记录。多个消费组可以消费相同的记录。为了可靠性,主题可以以复制因子为 3 的方式存储。主题可以有一个保留期,之后记录将被删除。所有这一切都是可能的,因为数据与铁不同,可以轻松复制。这是结束这篇文章的好地方。我们已经涵盖了 Kafka 的所有主要概念,您应该对 Kafka 的工作原理有一个大致的了解。
让我们用一个简短的回顾来结束:
Kafka 是一个分布式流媒体平台,通过跨多个服务器复制记录以持久的方式存储记录。主题由分区组成,按顺序存储记录。分区器决定哪些记录属于哪些分区。消费者组是可选的,有助于在消费者之间分配分区以实现可扩展性。偏移量作为消费者崩溃时的检查点提交。
简而言之,这就是 Kafka 的工作方式。
 
动画展示:https://zhuanlan.zhihu.com/p/438069222