这些图书有两列books
和readers
,其中books
和readers
分别是图书和读者ID。
我需要从这个表中删除阅读超过10本书的读者。
首先,我通过读者对书籍进行分组并获得这些群体的大小:
val byReader = data.map(r => (r.reader,r.book))
val booksByReader = byReader.groupByKey()
val booksByReaderCnts = booksByReader.map(tuple => tuple match {
case (reader, bookIter) => (reader, bookIter.size)
})
我在一个节点上运行它并尝试欺骗计算的分布式性质,并在Scala哈希映射中存储具有大书数的读者ID,作为副作用。我还以“标准Spark方式”过滤掉大量书籍的读者:
val maxBookCnt = 10
var hugeBookCntsMap: Map[Int, Int] = Map() // map to store reader id's with huge book counts
//Get readers with huge book counts
val hugeBookCnts = booksByReaderCnts.filter(tuple => tuple match {
case (reader: Int, cnt: Int) => hugeBookCntsMap += (reader -> cnt); cnt > maxBookCnt
})
Spark过滤按预期工作,并使用具有大书数的读者对创建RDD:
println("*** Huge cnts has: "+hugeBookCnts.count() + " elements")
hugeBookCnts.take(100).foreach(println)
另一方面,地图仍为空:
println("*** Map:")
hugeBookCntsMap.map(tuple => tuple match {
case (reader: Int, cnt: Int) => println("Reader: " + reader + " Cnt: " + cnt)
})
问题:
我的想法是创建一个Scala哈希映射来存储具有大量图书计数的用户的ID。接下来,我想通过检查用户是否在哈希中来过滤原始数据。哈希中的那些应该被过滤掉。显然,本地哈希映射没有获取数据,并且不能用于此目的。 *主要问题:如何过滤掉大阅读列表的读者记录? *
为什么本地哈希映射保持为空,前提是所有内容都在一个节点上运行?
Spark是否提供了组织不同进程之间共享的哈希映射的机制?
答案 0 :(得分:1)
有一种方法可以使用Spark来完成,而无需为单台计算机带来计数:
//count books by reader using reduceByKey transformation (thus no action yet)
// and filter readers with books count > 10
val readersWithLotsOfBooksRDD = data.map(r => (r.reader, 1)).reduceByKey((x, y) => x + y).filter{ case (_, x) => x > 10 }
// produces PairRDD
val readersWithBooksRDD = data.map( r => (r.reader, r.book))
//result
readersWithBooksRDD.subtractByKey(readersWithLotsOfBooksRDD).collect
回答您的其他问题:
更新hugeBookCntsMap的代码在不同JVM进程中的worker上执行。 Spark不会将工人的价值带回司机
Spark提供了几种机制,用于将值从驱动程序发送到工作程序,然后从工作程序发送回驱动程序。
一般情况下,如果应用程序的输出太大而无法放入单节点内存中 - 保存到HDFS或S3或其他一些分布式存储。