Spark - 如何使用有状态映射器对已排序的RDD进行flatmap?

时间:2015-08-16 04:48:19

标签: apache-spark rdd

基本上我有一个包含一系列事件的RDD / DataFrame(带有一些categoryId)。它们有时间戳,按时间排序。 我想要做的是扫描每个类别中的所有事件,同时保持/更新一些状态,记住某些事件是否被发现。一些例子:

  • 用户登录亚马逊(记录新会话ID,时间戳)
  • 用户将项目添加到basked(增量篮子大小为1)
  • 用户执行结帐(增加花费,输出rdd添加项目:sessionId + start_timestamp +数量,如果项目+花钱)
  • 用户在篮子中添加其他内容
  • 执行结帐 - >将下一项添加到输出rdd

我非常喜欢使用有状态映射器(它记住以前的项目)来做flatMap。映射器可以有一个"状态"的映射。按categoryId。但是有几百万个类别呢?有没有比按类别+时间戳排序更好的方法? 我还需要确保整个类别都在一个节点上。在这种情况下我应该按类别划分吗?我不确定数以百万计的分区是否好主意。

1 个答案:

答案 0 :(得分:1)

由于您的问题非常通用,因此您将得到一般答案。除非你有充分的理由拒绝,否则应使用Data FramesWindow Functions

上述第一项将为您提供Catalyst Optimizer的所有好处。第二个应提供您处理数据的操作,如您所述:

  • PARTITION BY - 按类别划分数据
  • ORDER BY - 按时间戳排序
  • FRAMEROWS / RANGE) - 窗口大小的可选限制
  • 实际functions执行所需的操作

旁注

  

我不确定数以百万计的分区是不是好主意。

不,它根本不是一个好主意,但通过某些键进行分区并不意味着您需要与唯一键数相同的分区数:

import org.apache.spark.HashPartitioner
val rdd = sc.parallelize(
   (1 to 10).flatMap(k => (1 to 100).map(_ => (k, scala.util.Random.nextInt)))
).partitionBy(new HashPartitioner(2))

在上面的示例中,您有10个不同的值,但只有2个分区。