Spark编程进阶
累加器
介绍与使用场景
当我们在驱动器端声明一个变量时,如果我们在计算过程中需要对变量进行修改,这个时候不同的执行器拿到的当前变量的一个副本。类似于Java多线程场景下对共享变量的操作。所以累加器作为一个驱动器端声明的变量,能保证多个执行器端操作的时候是不会发生变量冲突的情况。就像是Java中的AtomicInteger一样。
但是累加器具有容错性,当我们某个执行器节点宕机后,我们在当前节点转换生成的RDD需要基于谱系图重新执行,这时如果我们在转换操作中使用了累加器,就会导致累加器重复计算。所以我们最好保证累加器不是发送在转换操作(map,filter)中,而是使用在行动操作中。例如foreach().
代码demo
val count = new LongAccumulator()
sc.register(count) //需要先注册到SparkContext中
println("before isZero: " + count.isZero)
println("before count: " + count.count) //总共加了几个数字
println("before avg: " + count.avg) //数字的平均数
println("before sum: " + count.sum) //数字的和
/**
before isZero: true
before count: 0
before avg: NaN
before sum: 0
*/
val rdd = sc.textFile("path")
rdd.foreach(line => {
if (line.contains("hello")) {
count.add(5)
}
})
println("after isZero: " + count.isZero)
println("after count: " + count.count)
println("after avg: " + count.avg)
println("after sum: " + count.sum)
/**
after isZero: false
after count: 8
after avg: 5.0
after sum: 40
*/
广播变量
介绍与使用场景
如果一个变量很大,需要被所有的执行器节点访问,但是只需要具有可读权限即可。对于这种情况,我们可以使用广播变量,通过将变量广播,广播后的变量会被发送到各个节点一次,作为只读值处理。使得执行器节点上访问该变量不再是通过传参的方式,大大节省了网络开销提升了代码执行效率。
代码demo
//将rdd进行广播
val broadcast_rdd = sc.broadcast(rdd)
//访问广播后的变量
broadcast_rdd.value
性能优化情况
没有广播的情况:通过网络传输把变量发送到每一个 Task 中,会产生4个Number的数据副本,每个副本都会占用一定的内存空间,如果变量比较大,会导致则极易出现OOM。
使用广播的情况:通过Broadcast把变量传输到Executor的内存中,Executor级别共享唯一的一份广播变量,极大的减少网络传输和内存消耗!
广播变量的生命周期默认与SparkContext一致,序列化级别 是MEMORY_AND_DISK的(首先优先放在内存中,如果内存不够才放在磁盘上),所以如果对太大的对象进行广播会产生较大IO压力
分区操作
介绍与使用场景
某些变量是不需要对于RDD的每条数据都计算一遍的。像数据库连接这种,只需要在每个分区初始化一次就可以。所以提供分区操作,在每个分区中操作一次后,相当于这个变量在分区中是成员变量,供分区中RDD的每个元素访问,大大提高代码效率。
代码demo
mapPartitions() //先对分区进行迭代 然后对分区中元素迭代
mapPartitionsWithIndex() //迭代中含有分区序号
foreachPartitions()
rdd.filter(x => x != null).repartition(256).foreachPartition(partition => {
...
//分区变量声明
...
partition.foreach(pair => {
//具体处理每一个元素
}
}
数值RDD
API介绍
| 方法 | 含义 |
|---|---|
count() | 元素个数 |
mean() | 平均值 |
sum() | 总和 |
max() | 最大值 |
min() | 最小值 |
variance() | 方差 |
sampleVariance() | 采样中计算出的方差 |
stdev() | 标准差 |
sampleStdev() | 采样的标准差 |
stats() | 将以上结果全部计算出来封装到对象中返回 |
本文深入探讨Spark中的累加器、广播变量和分区操作,解析其工作原理、应用场景及代码实现。累加器用于并行计算中的共享变量,保证多线程操作的安全;广播变量用于提高大数据处理时的效率,减少网络传输;分区操作则针对特定变量优化,提升代码执行速度。
1439

被折叠的 条评论
为什么被折叠?



