VB_*_*VB_ 7 architecture streaming apache-spark lambda-architecture apache-flink
如您所知,Kappa体系结构是Lambda体系结构的某种简化。Kappa不需要批处理层,而是速度层必须保证历史数据重新计算的计算精度和足够的吞吐量(更多的并行性/资源)。
如果您需要基于历史数据进行分析,Kappa架构仍然需要两个服务层。例如,年龄小于2周的数据存储在Redis(流服务层),而所有较旧的数据存储在HBase的某个位置(批服务层)。
什么时候(由于Kappa体系结构)我必须将数据插入批处理服务层? 如果流传输层将数据紧紧地插入批处理和流服务层中,那么迟到数据又如何呢?还是流层应该定期将速度服务层备份到批服务层?
示例:假设数据源是Kafka,数据由Spark结构化流或Flink处理,接收器是Redis和HBase。什么时候写入Redis和HBase?
如果我们执行流处理,我们希望确保输出数据首先作为数据流提供。在您的示例中,这意味着我们将写入 Kafka 作为主要接收器。
现在你有两个选择:
现在的问题是如何处理最新数据。最好的解决方案是让框架通过水印来处理这个问题。也就是说,只有当框架确定没有迟到的数据到达时,数据才会在所有接收器上提交。如果这不起作用,因为您确实需要处理迟到的事件,即使它们晚得多晚到达并且仍然希望获得临时结果,则必须使用更新事件。
(根据OP的要求,我将在更新事件中添加更多详细信息)
在 Kafka Streams 中,默认情况下通过连续细化机制发出元素。这意味着,窗口聚合一旦拥有任何有效数据点就会发出结果,并在接收新数据时更新该结果。因此,任何迟到的事件都会被处理并产生更新的结果。虽然这种方法很好地减轻了用户的负担,因为他们不需要理解水印,但它有一些严重的缺点,导致 Kafka Streams 开发人员在 2.1 及更高版本中添加了Suppression 。
主要问题是,它给向下的用户处理中间结果带来了相当大的挑战,正如有关抑制的文章中也解释的那样。如果结果是临时的还是“最终的”(在所有预期事件都已被处理的意义上)并不明显,那么许多应用程序就很难实现。特别是,需要在消费者端复制窗口操作以获得“最终”值。
另一个问题是数据量爆炸。如果您有很强的聚合因子,那么使用基于水印的发射将在第一次操作后大幅减少数据量。然而,持续细化将添加恒定的体积因子,因为每个记录都会触发所有中间步骤的新(中间)记录。
最后,对您来说特别有趣的是,如果您有更新事件,如何将数据卸载到外部系统。理想情况下,您可以连续或定期卸载具有一定时间延迟的数据。该方法再次在消费者端模拟基于水印的发射。
可以对初始发射使用水印,然后对后期事件使用更新事件。然后减少所有“准时”事件的音量。例如,Flink 提供允许的延迟,以使窗口针对延迟事件再次触发。
此设置使卸载数据变得更加容易,因为如果实际发生了延迟事件,则只需将数据重新发送到外部系统。不过,应该对系统进行调整,因为延迟事件的情况很少见。