Dataframe Spark Streaming数据帧执行、有状态、分区本地groupBy,避免混乱
在这一点上感觉有点失落 我有一个基于Spark 2.4.2和Kafka的流应用程序,它将聚合(时间窗口)流写回Kafka: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。不幸的是,这不起作用 问题是,没有洗牌,实现这一目标的正确方法是什么?有吗 到目前为止,我探索的解决方案包
- [
]流式预分区数据帧(在键DF1
上,键
),即。 保证K到达同一分区的流 每次都是
- [
]我与DF1连接的查找表(~1000行)DF2
- GroupBy基于键和连续移动的1天窗口
流媒体不支持非基于时间的窗口
数据帧/数据集
)mapGroupsWithState
需要一个仅由GroupByKey提供的KeyValueGroupedDataset[K,V]
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")