Spark的两种共享变量方式

295 阅读5分钟

Spark有两种共享变量方式:广播变量(broadcast variable)与累加器(accumulator)。累加器用来对信息进行聚合,而广播变量用来高效分发较大的只读对象。

共享变量的作用

共享变量允许在spark应用的driver程序与executor之间共享信息。共享变量允许在RDD的各个partition之间高效地共享信息。

主要有两个作用:

  • 广播大的只读值。通过广播变量,可以高效地向所有工作节点发送一个大的数据集,而不需要这个数据集复制多份。
  • 在工作节点之间累加值。可以通过累加器实现对所有工作节点上的某个值进行更新。

共享变量的类型

  • 广播变量(Broadcast Variables):使用SparkContext的broadcast()创建广播变量,用于分发一个只读值的副本。
  • 累加器(Accumulators):使用SparkContext的accumulator()创建累加器,需要指定初始值和add操作,用于聚合每个partition的信息。

广播变量(Broadcast Variables)

  1. 创建广播变量

使用SparkContext的broadcast()方法创建广播变量。该方法会返回一个Broadcast对象。

broadcast_var = sc.broadcast(some_value)
  1. 在Driver程序中操作广播变量

在Driver程序中,可以通过Broadcast对象的value属性获取广播变量的值。

print(broadcast_var.value)
  1. 在RDD操作中使用广播变量

在RDD的map、filter等transformation操作中,可以直接通过广播变量的名称访问变量值,不需要通过value属性。

rdd.map(lambda x: x + broadcast_var)

Spark会将broadcast_var自动传输到各个工作节点上,map操作可以直接访问该变量。

  1. 关闭广播变量(可选)

使用完广播变量后,可以通过unpersist()方法关闭广播变量,释放资源。

broadcast_var.unpersist()

需要注意的是,广播变量是只读的,不能在transformation操作中修改其值。广播变量通常用于高效分发一个较大的只读参数。

累加器(Accumulators)

  1. 创建累加器

使用 SparkContext 的 accumulator() 方法创建累加器,并指定初始值和添加操作(add):

accum = sc.accumulator(0)
  1. 在 RDD 操作中使用累加器

在 RDD 的各个 partition 中,可以通过累加器的 add 方法来更新其值:

rdd.foreach(lambda x: accum.add(x))

需要注意的是,累加器只能在 action 操作中使用,不能在 transformation 中使用。

  1. 获取累加器的值

任务完成后,可以通过累加器的 value 属性获取聚合的结果:

print(accum.value)
  1. 关闭累加器(可选)

使用完成后,可以通过累加器的 destroy() 方法关闭累加器,释放资源:

accum.destroy()

累加器通常用于实现计数器、求和等功能,可以高效地聚合 RDD 中每个 partition 的信息。

广播变量(Broadcast Variables)解决了什么问题?

  1. 避免了重复传输大对象

Spark应用程序中经常会用到一些大的只读对象,如查找表或机器学习模型。如果不使用广播变量,这些大对象会跟其他数据一起,在任务之间进行传输,导致重复数据传输和延迟。

使用广播变量可以将这些大对象广播到所有节点,每个节点只保存一份,从而大大减少传输次数。

  1. 分布式共享只读状态

有时需要在不同的任务中共享只读的状态信息,如配置参数、机器列表等。广播变量为所有任务提供了一个共享的只读变量。

  1. 加速joins和聚合操作

将小表广播后,可以极大加速双边joins等操作,避免每次都需要传输这个小表。

  1. 减少内存压力

不使用广播变量,大对象会在每个任务中重新创建,占用大量内存。广播变量只存在一份,减轻了内存压力。

广播变量主要通过减少传输、分发只读状态、优化joins等操作来提升Spark程序的性能和降低内存消耗。

累加器(Accumulators)解决了什么问题?

  1. 分布式环境下的信息聚合

在分布式计算环境下,需要收集各个任务的统计和聚合信息,如数据条数、处理错误等。累加器提供了一个分布式聚合这些只能增加的统计值的机制。

  1. 获取副作用结果

Spark RDD的计算是确定性、无副作用的。但有时需要得到诸如数据条数等副产品结果。累加器就可以实现这种需要获取副作用结果的场景。

  1. 跟踪任务运行情况

可以自定义累加器来跟踪任务的运行指标,如运行时间、IO读写 bytes等,用来监控任务的执行情况。

  1. 实现类似MapReduce的Counter

累加器在概念上类似MapReduce中的Counter,提供了类似的聚合统计功能。

  1. 优化JOIN、GROUP BY等操作

累加器可以用来统计各个分区的大小、数量等信息,根据这些统计信息进行负载均衡,从而优化JOIN、GROUP BY等Shuffle操作。

累加器主要解决了在分布式环境下进行信息聚合统计的问题,可以获取任务执行过程中的一些统计指标,从而帮助监控和优化任务执行。