为什么在迭代RDD之后看不到局部变量值?

时间:2019-07-16 05:34:10

标签: scala apache-spark

嗨,我在Scala中为apache-spark编写代码。 我的本地变量“国家/地区”值在rdd迭代完成后没有反映出来。 在检查rdd迭代内的条件后,我正在为国家/地区变量分配值。直到rdd在控制权从循环值丢失中出来后,迭代值才在国家/地区变量中可用。

import org.apache.spark.sql.SparkSession
import java.lang.Long

object KPI1 {

  def main(args:Array[String]){
    System.setProperty("hadoop.home.dir","C:\\shivam docs\\hadoop-2.6.5.tar\\hadoop-2.6.5");

    val spark=SparkSession.builder().appName("KPI1").master("local").getOrCreate();
    val textFile=spark.read.textFile("C:\\shivam docs\\HADOOP\\sample data\\wbi.txt").rdd;

    val splitData=textFile.map{
      line=>{
        val token=line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
        (token(0),token(10).replace("\"","").replace(",", ""));
      }
    };

   // splitData.max()._2;
   var maxele=0l;
    var index=0;
    var country="";
    splitData.foreach(println);
    for(ele<-splitData){
      val data=Long.parseLong(ele._2);
      if(maxele<data){
        maxele=data;
        println(maxele);
        country=ele._1;
        println(country);
      }
    };
println("***************************** "+country+maxele);

spark.close()
  }
}

国家/地区变量值不应具有默认值。

2 个答案:

答案 0 :(得分:0)

forforeach都是宽操作。这意味着执行将在多个执行器上进行,这就是为什么您要为某些线程获取默认值的原因。我在具有4个执行程序的单节点集群中运行示例代码,您可以看到执行是在两个不同的执行程序中进行的(线程ID很明显)

样品

val baseRdd = spark.sparkContext.parallelize(Seq((1, 2), (3, 4)))

for (h <- baseRdd) {
  println( "Thread id " + Thread.currentThread().getId)
  println("Value "+ h)
} 

输出

Thread id 48
Value (1,2)
Thread id 50
Value (3,4)

如果您仍然希望获得预期的结果,请遵循以下任一选项

1。对spark上下文配置进行如下更改     master("local[1]")。这将使您的工作由单个执行者执行。

  1. collect()您的splitData在执行for(ele<-splitData){...}之前

注意:这两个选项均仅用于测试或实验目的,不适用于大型数据集。

答案 1 :(得分:0)

当您在执行器中使用变量时,Spark(YARN / Mesos等)会为每个执行器创建一个新实例。这就是为什么您看不到变量的任何更新的原因(该更新仅在执行器上发生,而没有更新到驱动程序中)。如果要完成此操作,则应使用累加器:

“ maxele”和“ country”均应为累加器。

您可以阅读有关herehere的信息