同步Spark任务

时间:2015-03-16 16:45:20

标签: synchronization apache-spark bigdata

我的Spark流程中有一个奇怪的行为,其行为如下:

  1. 读取参考文件,将其加载为map M并广播地图
  2. 读取第二个文件并将其转换为M
  3. 问题在于,在广播结束之前完成对M的转换调用,然后它不能按预期工作,因为M此时为空。

    我的问题是:如何让Spark在使用之前等待加载和广播对象?

    注意:我已经检查了通话时间,而且这些通话确实没有同步。然后,M确实正确加载。

    参考文件加载:

      object RefObjectUtil extends java.io.Serializable {
    
      var map = Map[String, RefObject]()
    
      def loadAndBroadcast(inputPath: String, sc: SparkContext) = {
        val data = read(inputPath, sc).collect
    
        val i = data.iterator
        while (i.hasNext) {
          val a = i.next
          map.put(a.getValue.toString, a)
        }
        sc.broadcast(map)
      }
    
      @throws(classOf[RefObject])
      def get(key: String): RefObject= {
        isLoaded()
        map.getOrElse(key, null)
      }
    
    
      private def isLoaded(): Unit = {
        if(map.isEmpty) {
          throw new RefObjectException("file has not been loaded. Add it into path argument of your job")
        }
      }
    

    然后是电话:

     def run() {
           RefObjectUtil.loadAndBroadcast(inputPath, sc)
           val data = read(inputToTransformPath, sc)
           transform(data)  //called without waiting end of refObject loading 
        }
    

    谢谢。

1 个答案:

答案 0 :(得分:0)

问题代码不起作用的原因与进程同步无关。代码可能在驱动程序中正确执行,但RefObjectUtil是一个单例对象,并且在引用时将在每个执行程序中再次初始化。此时,var map = Map[String, RefObject]()被初始化并且不包含任何数据。

在一个程序中看起来有两种Spark数据共享技术不合并。 要么我们使用'singleton object'模式来保存每个执行器上的数据,要么我们在驱动程序中组装数据并使用broadcast将其发送给执行程序。

'singleton object'模式更适合处理像DB连接这样的有状态资源,这似乎不是这里的情况。广播变量将是更好的选择。

让我们试着用一个例子说明用法:

问题代码的启发,此代码加载一些数据,从中创建地图并广播它。然后使用该地图来解析/翻译更大的数据集。注意如何使用broadcastVar.value在闭包内访问广播变量的内容。

// get data into map form
val dataMap =  val data = read(inputPath, sc).map{elem => (a.getValue.toString, a)}.collectAsMap
// broadcast the data
val broadcastMap = sc.broadcast(dataMap)

val dataToProcessRDD = ???
dataToProcessRDD.flatMap{item =>
    broadcastMap.value.get(item) //broadcastMap.value => returns the wrapped map instance
}