Kappa 架构:当插入 batch/analytic 服务层时

Kappa architecture: when insert to batch/analytic serving layer happens

如您所知,Kappa 架构是 Lambda 架构的某种简化。 Kappa不需要batch layer,而是speed layer在历史数据重新计算时要保证计算精度和足够的吞吐量(更多parallelism/resources)

Kappa 架构仍然需要两个服务层,以防您需要根据历史数据进行分析。例如,年龄小于 2 周的数据存储在 Redis(流式服务层),而所有较旧的数据都存储在 HBase(批处理层)的某个地方。

什么时候(由于 Kappa 架构)我必须将数据插入批处理服务层? 如果流层将数据立即插入到批处理和流服务层——那么延迟数据到达呢?还是流媒体层应该定期备份速度服务层到批量服务层?


示例:假设数据源是Kafka,数据由Spark Structured Streaming 或Flink 处理,接收器是Redis 和HBase。什么时候写入 Redis 和 HBase?

如果我们执行流处理,我们要确保输出数据首先作为数据流可用。在您的示例中,这意味着我们将 Kafka 作为主接收器写入。

现在你有两个选择:

  • 有从该 Kafka 主题读取并写入 Redis 和 HBase 的辅助作业。这就是 Kafka 的方式,因为 Kafka Streams 不支持直接写入任何这些系统,并且您需要设置 Kafka 连接作业。这些次要作业可以针对特定的接收器进行定制,但它们会增加额外的操作开销。 (这是您提到的备份选项的一部分)。
  • 使用 Spark 和 Flink,您还可以选择直接在您的工作中使用辅助接收器。您可以添加额外的处理步骤以将 Kafka 输出转换为更适合接收器的形式,但您在配置作业时会受到更多限制。例如在 Flink 中,您需要对 Kafka 接收器和 Redis/HBase 接收器使用相同的检查点设置。不过,如果设置成功,您只需要 运行 一个流媒体作业而不是 2 或 3 个。

迟到的活动

现在的问题是如何处理迟到的数据。最好的解决方案是让框架通过水印来处理。也就是说,只有当框架确定没有迟到的数据到达时,数据才会在所有接收器上提交。如果因为您确实需要处理迟到的事件而无法解决问题,即使它们到达的时间很晚,并且仍然希望获得临时结果,则必须使用更新事件。

更新事件

(应OP要求,我会在更新事件中添加更多细节)

在Kafka Streams中,默认情况下,元素是通过持续细化机制发出的。这意味着,窗口聚合一旦有任何有效数据点就会发出结果,并在接收新数据时更新该结果。因此,处理任何迟到的事件并产生更新的结果。虽然这种方法很好地减轻了用户的负担,因为他们不需要了解水印,但它有一些严重的缺点,导致 Kafka Streams 开发人员在 2.1 及更高版本中添加 Suppression

主要问题是它对向下用户处理中间结果提出了相当大的挑战,这在关于抑制的文章中也有解释。如果结果是临时的还是 "final"(在所有预期事件都已处理的意义上)不明显,那么许多应用程序将更难实现。特别是,需要在消费者端复制窗口操作以获得 "final" 值。

还有一个问题就是数据量膨胀了。如果你有一个强大的聚合因子,使用基于水印的发射将在第一次操作后大大减少你的数据量。但是,连续优化将添加一个恒定的体积因子,因为每个记录都会为所有中间步骤触发一个新的(中间)记录。

最后,您特别感兴趣的是,如果您有更新事件,如何将数据卸载到外部系统。理想情况下,您可以连续或定期卸载具有一定时滞的数据。该方法再次在消费者端模拟基于水印的发射。

混合选项

可以对初始发射使用水印,然后对延迟事件使用更新事件。然后减少所有 "on-time" 事件的音量。例如,Flink 提供 allowed lateness 让 windows 对延迟事件再次触发。

此设置使卸载数据变得更加容易,因为只有在实际发生延迟事件时才需要将数据重新发送到外部系统。应该对系统进行调整,尽管延迟事件很少见。