06-Spark进阶编程
前言
下面简单介绍一些更加深入、实用、高阶的Spark知识。
1 共享变量
通常在向Spark传递函数时,比如实用map()函数或filter()传递条件时,可以使用驱动器程序中定义的变量,但是集群中运行的每个任务都会得到这些变量的一份新的副本,更新这些副本的值也不会影响驱动器中对应的变量。
Spark的两个共享变量,累加器和广播变量,分别为结果聚合与广播这两种常见的通信模式突破了这一限制。 --《Spark快速大数据分析》
-
累加器
举个简单例子,如计算文本的空行。
blankLines = sc.accumulator(0),表示创建一个初始值为0的累加器。
第13行打印 blankLines 值为0,是因为 flatMap 是转化操作,即惰性。只有在执行了行为操作时,相应的计算才会实际执行。这里执行了 words.saveAsTextFile(“j”) 后,即可输出 blankLines 计算后的值。 -
广播变量
它可以让程序高效地向所有工作节点发送一个较大的只读值,以供一个或多个Spark操作使用。比如,如果你的应用需要向所有的节点发送一个较大的只读查询表,甚至是机器学习算法中的一个很大的特征向量,广播变量用起来都很顺手。 – 《Spark快速大数据分析》
因为书籍上的例子复杂,并且没有数据和结果,所以下面的测试数据是博主自己设计的,可能例子并不能很好的表达出广播变量的作用。
data为测试数据:
创建广播变量 addressBroadcast:
注意:addressBroadcast.value 为获取值
处理函数和计算结果:
2 基于分区的操作
基于分区对数据进行操作可以让我们为每个数据元素进行重复的配置工作。如打开数据库连接或创建随机数生成器等,都是我们应当尽量避免我每个元素都配置一次的工作。
Spark提供基于分区的map和foreach,让你的部分代码只对RDD的每个分区运行一次,这样可以帮助降低这些操作的代价。
简单来说,一个RDD由多个分区组成,一个分区由多个元素组成。而有些操作是对每个元素进行的,这样就会消耗不必要的资源,某些操作只需要对每个分区运行一次即可,而不需要对每个元素运行。
这些操作有:
3 与外部程序间的管道
Spark支持多种语言,但是某些计算使用多种语言相结合会使得应用更加简便、高效。
pip()方法就可以让我们使用任意一种语言实现Spark作业中的部分逻辑,只要它能读写Unix标准流就行。
例如,使用 R 语言用于计算距离,Python语言编写应用。
下面给出代码示例(注意红圈部分):
R语言计算距离:
文件名:./src/R/finddistance.R
在Python中使用pipe()调用 finddistance.R :
4 数值RDD的操作
在统计数据调用stats() 时通过一次遍历数据计算出来,即调用该方法后,下图中的数据已经计算出来:
当然,也可以调用单独的计算方法: