Spark实现提前中断正在运行的算子,并回到driver程序进行操作

让运行到一半的spark算子(如map,combineByKey等)在出现某些条件时可以中断运算,回到driver程序

最近实现导师交代的一个任务:大概就是利用spark实现一种快速算法,能够从多行数据中,挑选出头两个满足一个判定条件的匹配行,但是一个表中可能存在不止两个满足匹配条件的行,所以目标就是要在第一次遇到满足匹配条件的两个行时,就可以直接结束运算,以缩短运算时间。
在实现这个算法的过程中遇到一个需求:让spark算子执行到某一步时(即第一次遇到匹配行时),通过某些控制条件,让整个spark程序停止,跳出算子回到driver程序或者在那一步保存结果到文件。
在网上查了很久,找官方文档也没有找到直接能够实现的方法与接口,于是在想了很久之后用一种方法实现了:设置一个累加器(stopFlag),在driver程序中创建一个线程持续监听这个累加器的值,如果累加器的值发生了改变,则在driver中控制程序结束,在算子中,当出现需要提前结束算子运算的情况时(如第一次遇到匹配行),则改变累加器的值。通过这样一个方法实现了不用遍历完整个数据集,而提前结束算子的逻辑。

示例代码如下:

	//用累加器创造控制条件
    val stopFlag = sparkSession.sparkContext.longAccumulator("stopFlag")
    //创建线程用于持续监听累加器状态
    class Listener extends Runnable{
      var flag=true
      override def run(): Unit = {
        var flag=true
        while(flag){
          this.synchronized{
            //捕捉到累加器变化时,中断程序减少运算时间
            if(stopFlag.value==999){
              flag=false
              println("提前停止程序")
				//输出结果,结束程序
              sparkSession.stop()
              System.exit(1)
            }
          }
          Thread.sleep(500)
        }
      }
    }
    //创建额外线程持续监听累加器状况
    val e1 = new Listener
    val li = new Thread(e1)
    li.start()
    //在算子中,通过改变累加器的值,来向driver传输运算状态
	rdd1.foreach{x=>{
			if(//出现中断条件){
				stopFlag.add(999)
			}		
		}
	}

本文作为spark学习过程中的一个记录。

猜你喜欢

转载自blog.csdn.net/weixin_42836751/article/details/84872956