如你所知,kappa架构是lambda架构的简化。kappa不需要批处理层,而速度层在历史数据重新计算时必须保证计算精度和足够的吞吐量(更多的并行性/资源)。
kappa架构仍然需要两个服务层,以防您需要基于历史数据进行分析。例如,年龄<2周的数据存储在redis(流服务层),而所有较旧的数据存储在hbase(批服务层)的某处。
什么时候(由于kappa架构),我必须插入数据到批处理服务层?如果流媒体层立即将数据插入批处理层和流媒体服务层,那么延迟数据到达又如何呢?或者流媒体层应该定期备份速度服务层到批量服务层?
示例:假设数据源是kafka,数据由spark structured streaming或flink处理,汇是redis和hbase。何时写入redis&hbase?
1条答案
按热度按时间ocebsuys1#
如果我们执行流处理,我们希望确保输出数据首先作为数据流可用。在你的例子中,这意味着我们把Kafka当作一个主接收器来写。
现在您有两个选择:
有从Kafka主题读取并写入redis和hbase的辅助作业。这就是kafka的方式,因为kafka streams不支持直接写入这些系统中的任何一个,而您设置了kafka connect作业。这些辅助作业可以根据特定的接收器进行定制,但会增加额外的操作开销(这是您提到的备份选项)。
有了spark和flink,你也可以选择在工作中直接使用二次Flume。您可以添加额外的处理步骤来将kafka输出转换为更适合接收器的形式,但是在配置作业时您的限制更大。例如,在flink中,您需要对kafka接收器和redis/hbase接收器使用相同的检查点设置。不过,如果设置成功,您只需要运行一个流作业,而不是2或3个。
后期事件
现在的问题是如何处理最新的数据。最好的解决方案是让框架通过水印来处理。也就是说,当框架确定没有延迟数据到达时,数据只在所有接收器上提交。如果因为确实需要处理延迟事件而无法实现,即使它们到达的时间非常晚,并且仍然希望得到临时结果,那么就必须使用update events。
更新事件
(根据op的要求,我将为更新事件添加更多细节)
在kafka流中,默认情况下,元素通过一个连续的细化机制发出。这意味着,窗口聚合一旦有任何有效的数据点,就会发出结果,并在接收新数据时更新该结果。因此,对任何延迟事件进行处理并生成更新的结果。虽然这种方法很好地减轻了用户的负担,因为他们不需要理解水印,但它有一些严重的缺点,导致kafka流开发人员在2.1及以后的版本中添加了抑制。
主要的问题是,它对下行用户处理中间结果提出了相当大的挑战,这在关于抑制的文章中也作了解释。如果一个结果是临时的还是“最终的”(在所有预期事件都已处理的意义上)并不明显,那么许多应用程序就很难实现。特别是,窗口操作需要在用户端进行复制,以获得“最终”值。
另一个问题是数据量被放大了。如果你有一个强大的聚集因子,使用基于水印的发射将大大减少你的数据量后,第一次操作。但是,连续优化将添加一个恒定的体积因子,因为每个记录都会为所有中间步骤触发一个新的(中间)记录。
最后,您特别感兴趣的是,如果有更新事件,如何将数据卸载到外部系统。理想情况下,您可以连续或周期性地卸载具有一定时间延迟的数据。这种方法在用户端再次模拟了基于水印的发射。
混合选项
可以对初始发射使用水印,然后对后期事件使用更新事件。然后,所有“准时”事件的音量都会减小。例如,flink提供了允许的延迟,使windows可以再次触发延迟事件。
这种设置使得卸载数据变得更加容易,因为只有在发生延迟事件时才需要将数据重新发送到外部系统。不过,应该对系统进行调整,以确保延迟事件是一种罕见的情况。