【发布时间】:2016-04-10 08:58:08
【问题描述】:
在使用 Spark Streaming 处理连续的有限事件会话流时,选择无状态滑动窗口操作(例如 reduceByKeyAndWindow)与选择保持状态(例如通过 updateStateByKey 或新的 mapStateByKey)有哪些注意事项?
例如,考虑以下场景:
可穿戴设备可跟踪由以下人员进行的体育锻炼 佩戴者。该设备会自动检测锻炼何时开始, 并发出消息;锻炼时发出额外的信息 正在经历(例如心率);最后,当 练习完成了。
所需的结果是每个锻炼会话的汇总记录流。即同一会话的所有事件应聚合在一起(例如,以便每个会话可以保存在单个数据库行中)。请注意,每个会话的长度都是有限的,但来自多个设备的整个流是连续的。为方便起见,我们假设设备为每个锻炼会话生成一个 GUID。
我可以看到两种使用 Spark Streaming 处理此用例的方法:
-
使用非重叠窗口并保持状态。每个 GUID 保存一个状态,所有事件都与之匹配。当一个新的事件到来时,状态被更新(例如使用mapWithState),如果事件是“运动会话结束”,一个基于状态的聚合记录将被发出,并且key被移除。
使用重叠的滑动窗口,只保留第一个会话。假设一个长度为 2 且间隔为 1 的滑动窗口(见下图)。还假设窗口长度为 2 X(最大可能锻炼时间)。在每个窗口上,事件按 GUID 聚合,例如使用 reduceByKeyAndWindow。然后,在窗口后半部分开始的所有会话都被转储,剩余的会话被发射。这使得每个事件只使用一次,并确保属于同一会话的所有事件都将聚合在一起。
方法 #2 的示意图:
Only sessions starting in the areas marked with \\\ will be emitted. ----------- |window 1 | |\\\\| | ----------- ---------- |window 2 | |\\\\| | ----------- ---------- |window 3 | |\\\\| | -----------
我看到的优点和缺点:
方法 #1 的计算成本较低,但需要保存和管理状态(例如,如果并发会话的数量增加,状态可能会大于内存)。但是,如果最大并发会话数是有界的,这可能不是问题。
方法 #2 的成本是前者的两倍(每个事件处理两次),并且延迟更高(最大锻炼时间的 2 倍),但更简单且易于管理,因为不保留任何状态。
处理此用例的最佳方法是什么 - 这些方法中的任何一种是“正确”的方法,还是有更好的方法?
还应考虑哪些其他优点/缺点?
【问题讨论】:
标签: apache-spark spark-streaming