大规模数据处理14
1.RDD的结构:RDD结构中的其他的几个知识点:检查点Checkpoint、存储级别Storage Level和迭代函数Iterator
,如果任意一个RDD在相应的节点丢失,你只需要从上一步的RDD出发再次计算,便可恢复该RDD。
但是,如果一个RDD的依赖链比较长,而且中间又有多个RDD出现故障的话,进行恢复可能会非常耗费时间和计算资源。而检查点(Checkpoint)的引入,就是为了优化这些情况下的数据恢复。
很多数据库系统都有检查点机制,在连续的transcation列表中记录某几个transtraction后数据的内容,从而加快错误的恢复。
RDD检查点的思想与之类似,在计算过程中,对于一些计算过程比较耗时的RDD,我们可以将它缓存到硬盘或HDFS中,标记这个RDD有被检查点处理过,并且清空他的所有依赖关系,同时,给它新建一个依赖于checkpointRDD的依赖关系,checkpointRDD可以用来从硬盘中读取RDD和生成新的分区信息。
2.存储级别:
用来RDD持久化的存储级别,常用的有以下几种:
2.1 MEMORY_ONLY:只缓存在内存中,如果内存空间不够则不缓存多出来的部分。这是RDD存储级别的默认值。
2.2 MEMORY_AND_DISK:缓存在内存中,如果空间不够则缓存在硬盘中。
2.3 DISK_ONLY:只缓存在硬盘中。
2.4 MEMORY_ONLY_2和MEMORY_AND_DISK_2等:与上面的级别功能相同,只不过每个分区在集群中两个节点上建立副本。
3 迭代函数和计算函数是用来表示RDD怎样通过父RDD计算得到的,迭代函数首先判断缓存中是否有想要计算的RDD,如果有就直接读取,如果没有,就查找想要计算的RDD是否被检查点处理过。如果有,就直接读取,如果没有,就调用计算函数向上递归,查找父RDD进行计算。
RDD的转换操作
RDD的数据操作分为两种:转换transformation和动作action
转换就是用来把一个RDD转换成另一个RDD,而动作则是通过计算返回一个结果,所以map,filter,groupByKey等都属于转换操作。 >> 4.1 map 是最基本的转换操作,与mapreduce中的map一样,它把一个RDD中的所有数据通过一个函数,映射成为一个新的RDD,任何原RDD中的元素在新的RDD中都有且只有一个元素与之对应。
4.2 filter filter这个操作,是选择原RDD里所有数据中满足某个特定条件的数据,去返回一个新的RDD。
4.3 mapPartitions 它是map的变种,不同于map的输入函数是应用于RDD中每个元素,mapPartitions的输入函数是应用于RDD的每个分区,也就是把每个分区中的内容作为整体来处理的,所以输入函数的类型是Iterator[T] => Iterator[U]
4.4 groupByKey
groupByKey和SQL中的groupBy很类似,是把集合按某个Key来归类,返回的RDD中每个Key对应的一个序列
RDD的动作操作
5.1 Collect
RDD中的动作操作collect与函数式编程中的collect类似,它会以数组的形式,返回RDD的所有元素。需要注意的是,collect操作只有在输出数组所含的数据数量较小时使用,因为所有的数据都会载入到程序的内存中,如果数据量较大,会占用大量JVM内存,导致内存溢出。
5.2 Reduce
与MapReduce中的reduce类似,它会把RDD中的元素根据一个输入函数聚合起来。
5.3 Count
Count会返回RDD中元素的个数。
5.4 CountByKey
仅适用于Key-Value pair类型的 RDD,返回具有每个 key 的计数的<Key, Count>的map。
所有的转换操作都很懒,它只是生成新的RDD,并且记录依赖关系 ,但是Spark并不会立刻计算出新的RDD中各个分区的数值,直到遇到一个动作时,数据才会被计算,并且输出结果给Driver。
比如,在之前的例子中,你先对RDD进行map转换,再进行collect动作,这时map后生成的RDD不会立即被计算。只有当执行到collect操作时,map才会被计算。而且,map之后得到的较大的数据量并不会传给Driver,只有collect动作的结果才会传递给Driver。
Spark的执行操作流程:Spark在每次转换操作的时候,使用了新产生的RDD来记录计算逻辑,这样就把作用在RDD上的所有计算逻辑串起来,形成了一个链条,当对RDD进行动作时,Spark会从计算链的最后一个RDD开始,依次从上一个RDD获取数据并执行计算逻辑,最后输出结果
6 RDD的持久化(缓存)
每当我们对RDD调用一个新的action操作时,整个RDD都会从头开始运算。因