专栏原创出处:github-源笔记文件 (opens new window)github-源码 (opens new window),欢迎 Star,转载请附上原文出处链接和本声明。

# 1. 什么是共享变量

默认情况下,在一个对 RDD 操作的算子中如果使用到了外部 Driver 端定义的变量,这些变量将会被发送到每一个 Task 中,算子中的操作都是针对的这些变量的副本,并不会将结果更新到其他 Task 中,也不会更新到 Driver 端。在各任务之间支持通用的读写共享变量的效率是非常低的,但是 Spark 提供了两种常用的有限类型的共享变量:广播变量和累加器。

# 2. 广播变量

# 2.1.什么是广播变量

广播变量是由开发人员手动配置,将某个只读的变量广播到每个计算节点,每个计算节点上的所有 Task 使用这一个广播变量。同时 Spark 还采用了高效的广播算法分发这些变量,以减少网络传输上的开销。

  • 广播变量是只读属性的,无法改变它的值。

  • 由于闭包是将变量发送到了每一个 Task 中,当需要使用的变量是一个比较大的变量时,采用广播变量的方式要优于闭包的方式,可以有效地减少网络的传输和 Executor 端内存的占用。

# 2.2.如何使用广播变量

// 在 Driver 端广播一个变量
val broadcastVar = sc.broadcast(Array(1, 2, 3))

rdd.map(data=>{
  // 在 RDD 算子中获取广播变量
  val broadcastGet = broadcastVar.value
})

# 3. 累加器

# 3.1.什么是累加器

累加器是一个在 Driver 端定义的工具,主要用于所有计算节点上对一个变量进行的共享操作,比如实现计数器或求和的功能。

  • Spark 默认支持两种数字类型的累加器:Long 和 Double,开发人员可以通过继承 AccumulatorV2 来添加新类型的支持,自定义的时候结果类型可能与添加的元素类型不一致。

  • 在 Task 中不能读取累加器的值,只有在 Driver 端才可以拿到累加器的值。

  • 只有在触发了 action 动作之后,累加器的值才会更新。

  • Spark 保证每个任务只更新累加器一次,因此重启任务时,不会更新累加器的值;但是在任务运行中,如果某个 Task 或者 Stage 失败重试的时候,更新操作可能会执行多次。

# 3.2.如何使用累加器

// Driver 端定义一个 Long 类型的累加器
val accum = sc.longAccumulator("My Accumulator")

// 在算子中使用累加器求和
sc.parallelize(Array(1, 2, 3, 4)).foreach(x => accum.add(x))

// 在 Driver 端获取累加器的值
println(accum.value) // print 10
最后修改时间: 2/17/2020, 4:43:04 AM