Dataframe Spark Streaming数据帧执行、有状态、分区本地groupBy,避免混乱

Dataframe Spark Streaming数据帧执行、有状态、分区本地groupBy,避免混乱,dataframe,apache-spark,spark-streaming,Dataframe,Apache Spark,Spark Streaming,在这一点上感觉有点失落 我有一个基于Spark 2.4.2和Kafka的流应用程序,它将聚合(时间窗口)流写回Kafka: [DF1]流式预分区数据帧(在键上,键),即。 保证K到达同一分区的流 每次都是 [DF2]我与DF1连接的查找表(~1000行) GroupBy基于键和连续移动的1天窗口 问题: 洗牌。通过预先对数据集进行分区(在Kafka中),我希望实现分区本地groupBy。不幸的是,这不起作用 问题是,没有洗牌,实现这一目标的正确方法是什么?有吗 到目前为止,我探索的解决方案包

在这一点上感觉有点失落

我有一个基于Spark 2.4.2和Kafka的流应用程序,它将聚合(时间窗口)流写回Kafka:

  • [
    DF1
    ]流式预分区数据帧(在键
    上,键
    ),即。
    保证K到达同一分区的流
    每次都是
  • [
    DF2
    ]我与DF1连接的查找表(~1000行)
  • GroupBy基于键和连续移动的1天窗口
问题: 洗牌。通过预先对数据集进行分区(在Kafka中),我希望实现分区本地groupBy。不幸的是,这不起作用

问题是,没有洗牌,实现这一目标的正确方法是什么?有吗

到目前为止,我探索的解决方案包括:

  • “agg在窗口上方…”:流媒体中不支持(Spark抛出:
    流媒体不支持非基于时间的窗口
    数据帧/数据集
  • mapPartitions:不确定如何在状态(mapWithState)中使用因子
    mapGroupsWithState
    需要一个仅由GroupByKey提供的
    KeyValueGroupedDataset[K,V]
  • 我正在考虑的解决方案(不情愿):

  • dataframe上的mapPartitions,具有自定义状态管理。然而,这使得Spark的 有状态流,无用
  • 不知何故,将原始散列分区(来自Kafka数据帧)插入Spark,这样它就可以永久地处理洗牌(并且不使用默认的
    200
    ),但我还没有找到一个确定的源代码

  • 非常感谢您的帮助

    实际上,查找表导致了所有的混乱。我希望Spark更喜欢对较大的数据集进行分区,而不是对较小的查找表进行分区,但事实并非如此。它使用流式数据集,忽略分区,并将它们洗牌到查找表分区所在的位置


    当我按照流数据帧重新划分查找表时,Spark很高兴。尽管如此,Spark并不比较小的数据集更重视对较大数据集的分区,这与直觉相反。

    尝试使用
    DF1.join(broadcast(DF2),…)
    强制广播连接。这样可以防止混乱,并将密钥保留在原始分区中。@hristoilev我就是这么做的。它下降了一点,但仍然是一个相当大的混乱。我认为您的
    DF2
    足够小,并且位于单个分区中。在这种情况下,将其合并到单个分区中,然后尝试使用
    DF1.join(broadcast(DF2.coalesce(1)),…)
    进行广播连接。这是一个很好的建议,谢谢。DFs很小(从1000到100万行不等),但它们有很多这样的数据集,所以我不愿意将它们全部放在一个执行器上。
        DF1.join(DF2, "df1.a" === "df2.b", "left")
           .withWatermark("timestamp", "24 hours")
           .groupBy(window('timestamp, "24 hours"), 'theKey)
           .agg(collect_list('payload) as "payload")