Spark自学之路(八)——共享变量

共享变量

通常在向Spark传递函数时,比如使用map()函数或者用filter()传条件时,可以使用驱动器程序中定义的变量,但是在集群中运行的每个任务都会得到这些变量的一份新的副本,更新这些副本的值不会影响驱动器中的对应变量。Spark的两个共享变量,累加器与广播变量,分别为结果聚合与广播这两种常见的通信模式突破了这一限制。

累加器

提供了将工作节点中的值聚合到驱动器程序中的简单语法。

如在调试过程中对作业执行过程中的事件进行计数。(在Python中累加空行)


from pyspark import SparkContext
sc = SparkContext( 'local[*]', 'test')
file = sc.textFile(filepath)
#创建Accumulator[Int]并初始化为0
blankLines = sc.accumulator(0)

def extractCallSigns(line):
    global blankLines #访问全局变量
    if(line == ""):
        blankLines +=1
    return line.split(" ")

callSigns = file.flatMap(extractCallSigns)
callSigns.saveAsTextFile(filepath+"/callsigns")
print(blankLines.value)

注意:只有在执行saveAsTextFile()行动操作之后才能看到正确的计数,因为行动操作前的转化操作flatMap()是惰性的,所以作为计算副产品的累加器只有在惰性的转化操作flatMap()被saveAsTextFile()行动操作强制触发时才会开始求值。

累加器的用法:

  1. 通过驱动器中调用SparkContext.accumulator(initiaValue)方法,创建出存有初始值的累加器。返回值org.apache.spark.Accumulator[T],其中T是初始值initialValue的类型
  2. Spark闭包里的执行器代码可以使用累加器的 +=方法增加累加器的值。
  3. 驱动器程序可以调用累加器的value属性来访问累加器的值

注意:工作节点上的任务不能访问累加器上的值。从这些任务角度来看,累加器是一个只读变量。

广播变量

它可以让程序高效地向所有工作节点发送一个较大地只读值,以供一个或者多个Spark操作。

广播变量允许程序员在每台机器上保留一个只读变量,而不是随副本一起发送它的副本。 例如,它们可用于以有效的方式为每个节点提供大输入数据集的副本。 Spark还尝试使用有效的广播算法来分发广播变量,以降低通信成本。

Spark动作通过一组阶段执行,由分布式“shuffle”操作分隔。 Spark自动广播每个阶段中任务所需的公共数据。 以这种方式广播的数据以序列化形式缓存并在运行每个任务之前反序列化。 这意味着显式创建广播变量仅在跨多个阶段的任务需要相同数据或以反序列化形式缓存数据很重要时才有用。

可以通过调用SparkContext.broadcast(v)来从一个普通变量v中创建一个广播变量。这个广播变量就是对普通变量v的一个包装器,通过调用value方法就可以获得这个广播变量的值:

from pyspark import SparkContext
sc = SparkContext( 'local[*]', 'test')
broadcastVar = sc.broadcast([1, 2, 3])
broadcastVar.value
#[1,2,3]

这个广播变量被创建以后,那么在集群中的任何函数中,都应该使用广播变量broadcastVar的值,而不是使用v的值,这样就不会把v重复分发到这些节点上。此外,一旦广播变量创建后,普通变量v的值就不能再发生修改,从而确保所有节点都获得这个广播变量的相同的值。

你可能感兴趣的:(Spark)