Spark:过滤掉汇总数据?

时间:2015-06-08 12:34:40

标签: scala hash apache-spark filtering

这些图书有两列booksreaders,其中booksreaders分别是图书和读者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) 
    })

问题:

  1. 我的想法是创建一个Scala哈希映射来存储具有大量图书计数的用户的ID。接下来,我想通过检查用户是否在哈希中来过滤原始数据。哈希中的那些应该被过滤掉。显然,本地哈希映射没有获取数据,并且不能用于此目的。 *主要问题:如何过滤掉大阅读列表的读者记录? *

    1. 为什么本地哈希映射保持为空,前提是所有内容都在一个节点上运行?

    2. Spark是否提供了组织不同进程之间共享的哈希映射的机制?

1 个答案:

答案 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

回答您的其他问题:

  1. 更新hugeBookCntsMap的代码在不同JVM进程中的worker上执行。 Spark不会将工人的价值带回司机

  2. Spark提供了几种机制,用于将值从驱动程序发送到工作程序,然后从工作程序发送回驱动程序。

    • 从驱动程序到工作人员 - 关闭 - hugeBookCntsMap的值被序列化并发送给工作人员。但是对worker的hugeBookCntsMap的更改不会发送回驱动程序。这旨在用于小对象和功能。只读。
    • 从驱动程序到工作程序 - 广播变量 - 这用于大型对象。只读。
    • 从工人到司机 - 工作收集行动或减少操作 - 就像我的计算代码一样。工人生成元组并将它们聚合并收集回驱动程序
    • 从工人到司机 - 使用蓄电池。但是,应该可以汇总结果
  3. 一般情况下,如果应用程序的输出太大而无法放入单节点内存中 - 保存到HDFS或S3或其他一些分布式存储。