输入1: KV数据流
输入2:一些静态数据分区(用于处理输入1中的流)
可以将问题建模为以下图像:
与HDFS / RDD分区共存位置:我们如何确保流媒体任务Map1,Map2和Map3在存在HDFS / RDD分区的计算机上运行?
图片说明:假设 K 是流式密钥(不是元组)。 First Map将其转换为元组(具有空值)并将其广播到3个Mappers。每个映射器都在包含RDD(或HDFS文件,第二个输入和静态数据)的不同分区的不同节点上运行。每个Mapper使用RDD分区来计算密钥的值。最后,我们想要聚合键的值(使用reduceByKey _ + _)。
答案 0 :(得分:1)
如果我理解正确:
K
是您RDD
通过***DStream
工作获得的streaming
。我不知道您的传入数据的来源。此数据基本上是密钥的array/seq/list
。PairedRDD
形式的<K, Object>
。在Object
,您要为Val_n
中的密钥提取incoming RDD
。shuffle
(或查找)过程中避免/最小化join
。为此,最好的策略是使用incoming RDD
和Static RDD
的{{3}}操作,两个RDD partitioned
使用相同的Join
。如果数据RDD中的任何一个比另一个小得多,您可以探索broadcasting
较小的数据。我最近在我的项目中尝试了这个并在帖子中分享了经验:Partitioner
修改:由于您要处理密钥,K
(假设K =设置{K1,K2 ... Kn}),使用StaticRDD
,对于分区,我建议采用如下方法。我没有检查语法和正确性,但你会得到意图。
val kRddBroadcastVar = .... // broadcasted variable
val keyValRDD = staticRDD.mapPartitions {
iter => transformKRddToTuple2Events(iter, kRddBroadcastVar )
}
def transformKRddToTuple2Events( iter: Iterator[Object], kRddBroadcastVar: List[KeyObjectType] ) : Iterator[(keyObjectType, valueObjectType )] {
val staticList = iter.toList
val toReturn = kRddBroadcastVar.map ( k => getKeyValue(k, staticList) )
toReturn.iterator
}
val outRdd = keyValRDD.reduceByKey( _ + _ )
如果这有意义,请接受此答案。
答案 1 :(得分:1)
您的静态RDD是否足够小以便缓存。在这种情况下,Spark将尝试在这些节点上运行流任务。虽然不能保证。
此外,如果参考数据的尺寸很小,为什么不广播该数据集。
我们一直在尝试解决有关数据存储SnappyData(http://www.snappydata.io/)中首选位置的类似问题,其中数据位置是一等公民。