我有一个Dstream(K,V)。我的用例需要按顺序处理具有相同键的所有元组。这个过程就像吼叫:
val filestream=//..
fileStream.foreachRDD(r=>
{
r.foreachparttion(p=>
{
p.foreach(x=>
{
//x get the sate from Hbase
//updates Hbase state for the key=k using the v and the retrieved state
})})})
因为对于每个元组和相应的密钥,我在HBase中都有状态,所以我需要确保所有具有相同密钥的元组每次都由一个CPU核心在一个分区中处理,因此每个元组都获得有效状态(不是过时和无效的)..流应用程序的并发性是1。
现在我想知道上面的代码是否足以满足我的上述要求,或者我是否需要进一步对键值进行分组(例如,使用combinebykey in this thread)?
我想知道是否访问每个分区中RDD中的每个元组(对于每个批处理间隔 - 如下所示)
p.foreach(x=>
{
//x get the sate from Hbase
//updates Hbase state for the key=k using the v and the retrieved state
})
可以是顺序的,也可以是并行的?
答案 0 :(得分:1)
一般情况下,在Spark Streaming中,对于哪个键接收器没有保证。特定的接收器实现可能提供保修或实现它的可能性。 例如,Kafka消费者将为您提供保证,即在一个执行程序上使用来自一个分区的所有数据,因此将相同的密钥放在同一分区中将实现预期目标。
在一般情况下,为了确保相同的密钥位于同一个Spark分区中,我们需要重新分区数据。但是为了确保按顺序处理来自一个密钥的数据,我们需要更进一步,将每个密钥的数据放在一起。可以使用groupByKey
来完成这两个步骤的组合。一旦我们以key -> [data1, ..., datan]
的形式获得数据,我们只需要从db请求当前(k,v)
来完成该过程。
就代码而言,我们会有类似的内容:
fileStream.foreachRDD{rdd =>
val dataPerKey = rdd.map(entry => (key(entry),value(entry))).groupByKey()
dataPerKey.forEachPartition{iter =>
val dataMap = iter.toMap
val keys = dataMap.keys
// val dbState = HBase.get(keys)
// val newData = process dataMap + dbState
HBase.write(newData)
}
}