Apache spark Spark流:无状态重叠窗口与保持状态
在使用Spark Streaming处理连续、有限事件会话流时,选择无状态滑动窗口操作(例如ReduceByAndWindow)与选择保持状态(例如通过updateStateByKey或新的mapStateByKey)有哪些注意事项Apache spark Spark流:无状态重叠窗口与保持状态,apache-spark,spark-streaming,Apache Spark,Spark Streaming,在使用Spark Streaming处理连续、有限事件会话流时,选择无状态滑动窗口操作(例如ReduceByAndWindow)与选择保持状态(例如通过updateStateByKey或新的mapStateByKey)有哪些注意事项 例如,考虑下面的场景: 一种可穿戴设备可以跟踪由用户进行的体育锻炼 佩戴者。当运动开始时,设备会自动检测, 发出信息,;在练习时发出其他消息 正在进行(如心率);最后,当 练习完成了 期望的结果是每个练习会话的聚合记录流。i、 e.同一会话的所有事件应聚合在一起(例
例如,考虑下面的场景:
一种可穿戴设备可以跟踪由用户进行的体育锻炼 佩戴者。当运动开始时,设备会自动检测, 发出信息,;在练习时发出其他消息 正在进行(如心率);最后,当 练习完成了 期望的结果是每个练习会话的聚合记录流。i、 e.同一会话的所有事件应聚合在一起(例如,使每个会话可以保存在单个DB行中)。请注意,每个会话的长度有限,但来自多个设备的整个流是连续的。为方便起见,假设设备为每个练习会话生成GUID 我可以看到使用Spark Streaming处理此用例的两种方法:应该考虑哪些其他优点/缺点?通常没有正确的方法,每个方法都有权衡。因此,我将添加额外的方法来混合,并将概述我对其利弊的看法。所以你可以决定哪一个更适合你 外部状态方法(方法3) 您可以在外部存储器中累积事件的状态。卡桑德拉经常被用来做这件事。您可以分别处理最终事件和正在进行的事件,例如,如下所示:
val流=。。。
val ongoingeventstream=stream.filter(!isFinalEvent)
val finalEventsStream=stream.filter(isFinalEvent)
OnGoingEventStream.foreachRDD{/*casssandra中的累积状态*/}
finalEventsStream.foreachRDD{/*在casssandra中完成状态,如果需要,移动到最终目标*/}
trackStateByKey进近(进近#1.1)
对于您来说,这可能是一个潜在的最佳解决方案,因为它消除了updateStateByKey的缺点,但考虑到它只是作为Spark 1.6发行版的一部分发布的,它也可能有风险(因为出于某些原因,它不是很受欢迎)。如果您想了解更多信息,可以使用作为起点
赞成/反对
进近#1(updateStateByKey)
赞成的意见
- 易于理解或解释(对团队其他成员、新员工等)(主观)
- 存储:更好地利用内存只存储最新的运动状态
- 存储:将只保留正在进行的练习,并在完成后立即丢弃
- 延迟仅受每个微批处理的性能限制
- 存储:如果密钥数(并发练习)很大,则可能无法放入集群的内存中
- 处理:它将为状态映射中的每个键运行updateState函数,因此,如果并发练习的数量很大,性能将受到影响
- 处理在某些情况下(取决于数据)可能比updateStateByKey更有效,因为updateStateByKey倾向于在每个键上运行更新,即使没有实际更新
- “最大可能的运动时间”——这听起来像是一个巨大的风险——根据人类行为,它可能是相当任意的时间。有些人可能会忘记“完成练习”。这也取决于锻炼的种类,但可能从几秒到几小时不等,当你希望快速锻炼的潜伏期较低时,就必须将潜伏期保持在可能存在的最长锻炼的潜伏期
- 感觉很难向他人解释它将如何工作(主观)
- 存储:必须将所有数据保存在窗口框架内,而不仅仅是最新的数据。只有当窗口从这个时间段滑开时,而不是当练习实际完成时,才会释放内存。虽然如果你只保留最后两个时间段可能不会有太大的区别,但如果你试图通过更频繁地滑动窗口来获得更大的灵活性,那么这种差异就会增加
Only sessions starting in the areas marked with \\\ will be emitted.
-----------
|window 1 |
|\\\\| |
-----------
----------
|window 2 |
|\\\\| |
-----------
----------
|window 3 |
|\\\\| |
-----------
ongoingEventsStream.foreachRDD { /*accumulate state in casssandra*/ }