spark笔记总结

RDD基础:


transformation操作:由一个RDD生成新的RDD, 转化操作是惰性的

action操作:由RDD生成其他数据类型,向驱动器返回结果或者把结果写入外部文件系统。

默认情况下,RDD会在每次进行action操作时重新计算。

常用转化操作:

每次针对一个元素的操作:

filter:过滤出符合条件的数据,蚕食不改变输入的原始数据。

map:对每个元素返回一个输出元素,返回类型不需要喝输入的类型一样。

flatMap:对每个输入元素生成多个输出元素,返回值是一个序列的迭代器,输出的RDD倒不是由迭代             器组成的,我们得到的是一个包含各个迭代器可访问的所有元素的RDD。

(理解map和flatMap的区别:map输出的元素个数和输入的个数相同,但是每个元素的类型可能变了,比如由一个String变成了一个String数组。而flatMap将这些元素拍扁,这样个数可能变多了。)


伪集合操作:

RDD本身不是严格意义上的集合,但是支持数学上的集合操作,比如合并和相交操作,但是这些操作要求RDD是相同数据类型的。

distinct:去除重复元素, 为了确保元素只有一份,所以要经过网络混洗,因此开销比较大。

union:返回一个包含两个RDD中所有元素的RDD。不需网络混洗。

intersection:返回两个RDD中都有的元素。需网络混洗。

subtract:返回只存在第一个RDD而不存在第二个RDD中的所有元素组成的RDD。需网络混洗。

cartesian:返回两个RDD的笛卡尔积。


常用行动操作:

行动操作:

take:获取RDD中少量的元素到本地。

top:获取前几个元素。

collect:获取整个RDD中的元素到本地,因此数据规模大的时候不宜使用。

reduce:将操作RDD的两个元素并返回同样类型的一个元素。要求输入和输出类型一样。

fold:和reduce一样,外加一个计算的初始值。要求输入和输出类型一样。

aggregate:可以代替map后接fold方式,不要求输入和输出类型一样。

takeSample:从数据中获取一个采样,并指定时候替换。

count:计算RDD中元素个数。

countByValue:各元素在RDD中出现的次数。

foreach:不论什么情况,都可以使用foreach行动操作来对RDD中的每个元素进行操作,而不需要把RDD发回本地。


键值对操作:


键值对RDD通常用来进行聚合计算。当需要把一个普通的RDD转为par RDD时,可以调用map函数实现。不论是基础RDD的转化操作还是行动操作,在pair RDD上同样可用。

常用动机操作:

1.pair RDD动机操作:

countByKey:对每个键对应的元素分别计数。

collectAsMap:将结果以映射表的形式返回,以便查询。

lookup:返回制定键对应的所有值。

常用转化操作:

1.每次针对一个元素的操作:

reduceByKey:合并具有相同键的值。

groupByKey:对具有相同键的值进行分组。

combineByKey:使用不同的返回类型合并具有相同键的值。

mapValues:对pair RDD中的每个值应用一个函数而不改变键。

flatMapValues:对pair RDD中的每个值应用flatMap,然后将返回的每个元素都生成一个对应原键的键值对纪录。

keys:返回一个仅包含键的RDD。

values:返回一个仅包含值的RDD。

sortByKey:返回一个根据键排序的RDD。

2.针对两个pair RDD的转化操作。

subtractByKey:删除第一个pair RDD中与第二个pair RDD中键相同的元素。

join:对两个pair RDD进行内链接。

rightOuterJoin:对两个pair RDD进行右外链接。确保第二个RDD键一定存在。

leftOutJoin:对两个pai RDD进行左外链接。确保第一个RDD键一定存在。

cogroup:将两个RDD中拥有相同键的数据分组到一起。


向spark传递函数时需要注意:

python不要传某个对象的成员活着对某个对象的一个字段的引用,这样spark会将整个对象都发到工作节点上,高效的方式的用局部变量记录需要传的值。

scala也同样存在上述问题。解决办法也是用局部变量接收需要传的字段。


持久化:

scala和java中,默认情况下persist会把数据以序列化的形式缓存在JVM的堆空间中,在python中,会始终序列化存储的数据,所以持久化级别默认值就是以序列化后的对象存储在jvm堆空间中。当把数据写到磁盘或者堆外存储时,也总是使用序列化后的数据。

如果缓存的数据太多,内存中放不下,spark会自动利用最近最少使用的缓存策略把最老的分区从内存中移除。


分区:

pair RDD都可以进行分区,可以调用partitionBy指定分区方式,partitionBy是一个转化操作,因此它不改变原来的RDD,而是返回一个新的RDD。当调用partitionBy之后记得进行persist,否则分区操作带来的好处将被抵消。

能从分区中获得好处的操作包括:cogroup, groupWith, join, leftOuterJoin, rightOuterJoin, groupByKey, reduceByKey, combineByKey, lookup。

对于二元操作,输出数据分区方式取决于父RDD的分区方式,默认情况下,结果会采用哈希分区,如果父RDD以设置过分区方式,那么结果将采用那种分区方式,如果两个RDD都设置过分区方式,结果RDD将采用第一个父RDD的分区方式。


Spark运行时架构:

Spark集群采用的是主/从结构,中央协调节点称为驱动器节点,与之对应的工作节点被称为执行器节点(驱动器节点和执行器节点都是逻辑概念)。Spark应用通过一个叫做集群管理器(例如spark自带的独立集群管理器,Yarn,Mesos等。)的外部服务在集群中的机器上启动。

驱动器节点:

执行main方法的进程,它执行用户编写的用来创建SparkContext,创建RDD,以及进行RDD的转化和行动操作的代码。(注意,具体的RDD task在执行器里执行。)

职责:1.将用户程序转为任务。

2.对执行器节点调度任务。

执行器节点:

作用:1.负责运行组成Spark应用的任务,并将结果返回给驱动器进程。

2.通过自身的块管理器为用户程序中要求缓存的RDD提供内存式存储。


集群上运行spark程序的详细过程:

1. 用户通过spark-submit脚本提交应用。

2. spark-submit脚本启动驱动器程序,调用用户自定义的main方法。

3. 驱动器程序与集群管理器通信,申请资源以启动执行器结点。

4. 集群管理器为驱动器程序启动执行器结点。

5. 驱动器进程执行用户应用中的操作,根据程序中所定义的对RDD的转化和行动操作,驱动器节点把工作以任务的形式发送到执行器进程。

6. 任务在执行器程序中进行计算并保存结果。

7. 如果驱动器程序的main方法退出,或者调用了SparkContext.stop,驱动器程序会终止执行器进程,并且通过集群管理器释放资源。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容