起因:在学习FP-Growth算法时,导入数据建立好Tree后,对输入项A查找其频繁项时,需要在driver端记录下输入项A的支持度计数总和,此时出现在executor端对driver端的变量的值进行更改后,driver端的变量值却没有改变,在好心人的帮助下,发现spark有Broadcast和Accumulator。
错误案例:同一个变量打印出现不同结果
var goodsFreq = 0L val freqItemsets = fpModel.freqItemsets.cache() freqItemsets.foreach{f => if(f.items.mkString == test.mkString){ goodsFreq = f.freq println("value1:"+goodsFreq) } }
value1:2513
value2:0
正确案例:累加器(accumulator)是Spark中提供的一种分布式的变量机制
var goodsFreq = spark.sparkContext.longAccumulator val freqItemsets = fpModel.freqItemsets.cache() freqItemsets.foreach{f => if(f.items.mkString == test.mkString){ goodsFreq.add(f.freq) println("value1:"+goodsFreq) } } println("value2:"+goodsFreq) value1:LongAccumulator(id: 125, name: None, value: 2513) value2:LongAccumulator(id: 125, name: None, value: 2513) 广播变量:通过广播变量将变量复制到executor,每个task执行时,不需要通过网络再次传输变量,而是通过blockmanager获取变量,而不是从Driver获取变量,从而提升了效率。 广播变量是只读类型,不可重写。定义广播变量方式 val bc = sc.broadcast(需要广播的变量) 广播变量的使用方式 dc.value广播变量值 累加器:是spark中提供的一种分布式变量机制,在executor中只能写,不能读,但是能在driver端读。 定义方式: var accu = sc.longAccumulator 累加器使用方式 val result = accu.value