最近开始学习spark的的东西,在学习之前可以去学习一些scala的,毕竟源码是scala的,有些东西操作习惯是从scala中扩展出来的。
下面切入正题
可以参考,下面的官方文档
http://spark.apache.org/docs/1.6.0/programming-guide.html#resilient-distributed-datasets-rdds
RDDs(Resilient Distributed Datasets)
可以翻译成弹性分布式数据集合。
RDD是只读的、分区记录的集合。RDD只能基于在稳定物理存储中的数据集和其他已有的RDD上执行确定性操作来创建。这些确定性操作称之为转换,如map、filter、groupBy、join(转换不是程开发人员在RDD上执行的操作)。RDD作为数据结构,本质上是一个只读的分区记录集合。一个RDD可以包含多个分区,每个分区就是一个dataset片段。RDD可以相互依赖。如果RDD的每个分区最多只能被一个Child RDD的一个分区使用,则称之为narrow dependency;若多个Child RDD分区都可以依赖,则称之为wide dependency。
其实就是一种数据的分裂式的存储,将原来的一张大表,拆成小的多个组成部分,在使用时,可以重组起来进行操作,利用一些数据的局部化操作等。
Spark之所以将依赖分为narrow与wide,基于两点原因。
首先,narrow dependencies可以支持在同一个cluster node上以管道形式执行多条命令,例如在执行了map后,紧接着执行filter。相反,wide dependencies需要所有的父分区都是可用的,可能还需要调用类似MapReduce之类的操作进行跨节点传递。
其次,则是从失败恢复的角度考虑。narrow dependencies的失败恢复更有效,因为它只需要重新计算丢失的parent partition即可,而且可以并行地在不同节点进行重计算。而wide dependencies牵涉到RDD各级的多个Parent Partitions。下图说明了narrow dependencies与wide dependencies之间的区别:
本图来自Matei Zaharia撰写的论文An Architecture for Fast and General Data Processing on Large Clusters。图中,一个box代表一个RDD,一个带阴影的矩形框代表一个partition。
根据宽窄依赖进行stage的切分。
RDDs的操作分为两类:
1.是转换操作,就是从一种RDD->RDD ,一种RDD到另一种RDD只是做一种数据的转换。
2.是进行执行操作,就是action的,具体是在RDD上进行操作输出不是RDD的操作。
一般action会真实的触动整个job的执行,这个就是关于DAG的优化中所用到的一种,也就是再次体现了spark与stom的延迟性。
常用的数据转换操作有
1.Map
map是对RDD中的每个元素都执行一个指定的函数来产生一个新的RDD;RDD之间的元素是一对一关系
2.filterFilter是对RDD元素进行过滤;返回一个新的数据集,是经过func函数后返回值为true的原元素组成;
3.flatMap
flatMap类似于map,但是每一个输入元素,会被映射为0到多个输出元素(因此,func函数的返回值是一个Seq,而不是单一元素), RDD之间的元素是一对多关系;
4.mapPartitions
mapPartitions是map的一个变种。map的输入函数是应用于RDD中每个元素,而mapPartitions的输入函数是每个分区的数据,也就是 把每个分区中的内容作为整体来处理的。
5.mapPartitionsWithIndex
mapPartitionsWithSplit与mapPartitions的功能类似, 只是多传入split index而已,所有func 函数必需是 (Int, Iterator<T>) => Iterator<U> 类型。
6.sample
sample(withReplacement,fraction,seed)是根据给定的随机种子seed,随机抽样出数量为frac的数据。withReplacement:是否放回抽 样;fraction:比例,0.1表示10%
7.union
union(otherDataset)是数据合并,返回一个新的数据集,由原数据集和otherDataset联合而成。
8.intersection
intersection(otherDataset)是数据交集,返回一个新的数据集,包含两个数据集的交集数据
9.distinct
distinct([numTasks]))是数据去重,返回一个数据集,是对两个数据集去除重复数据,numTasks参数是设置任务并行数量。
10.groupByKey
groupByKey([numTasks])是数据分组操作,在一个由(K,V)对组成的数据集上调用,返回一个(K,Seq[V])对的数据集
11.reduceByKey
reduceByKey(func, [numTasks])是数据分组聚合操作,在一个(K,V)对的数据集上使用,返回一个(K,V)对的数据集,key相同的值, 都被使用指定的reduce函数聚合到一起
12.aggregateByKey
aggreateByKey(zeroValue: U)(seqOp: (U, T)=> U, combOp: (U, U) =>U) 和reduceByKey的不同在于,reduceByKey输入输出都是(K, V),而aggreateByKey输出是(K,U),可以不同于输入(K, V) ,aggreateByKey的三个参数:
zeroValue: U,初始值,比如空列表{} ;
seqOp: (U,T)=> U,seq操作符,描述如何将T合并入U,比如如何将item合并到列表 ;
combOp: (U,U) =>U,comb操作符,描述如果合并两个U,比如合并两个列表 ;
所以aggreateByKey可以看成更高抽象的,更灵活的reduce或group
13.combineByKey
combineByKey是对RDD中的数据集按照Key进行聚合操作。聚合操作的逻辑是通过自定义函数提供给combineByKey。
combineByKey[C](createCombiner: (V) ⇒ C, mergeValue: (C, V) ⇒ C, mergeCombiners: (C, C) ⇒ C, numPartitions: Int):RDD[(K, C)]把(K,V) 类型的RDD转换为(K,C)类型的RDD,C和V可以不一样。
14.sortByKey
sortByKey([ascending],[numTasks])是排序操作,对(K,V)类型的数据按照K进行排序,其中K需要实现Ordered方法。
15.join
join(otherDataset, [numTasks])是连接操作,将输入数据集(K,V)和另外一个数据集(K,W)进行Join, 得到(K, (V,W));该操作是对于相同K 的V和W集合进行笛卡尔积 操作,也即V和W的所有组合;
16.cogroup
cogroup(otherDataset, [numTasks])是将输入数据集(K, V)和另外一个数据集(K, W)进行cogroup,得到一个格式为(K, Seq[V], Seq[W]) 的数据集.
17.cartesian
cartesian(otherDataset)是做笛卡尔积:对于数据集T和U 进行笛卡尔积操作, 得到(T, U)格式的数据集
action操作
1.reduce
reduce(func)是对数据集的所有元素执行聚集(func)函数,该函数必须是可交换的。
2.collect
collect是将数据集中的所有元素以一个array的形式返回。
3.count
返回数据集中元素的个数。
4.first
返回数据集中的第一个元素, 类似于take(1)。
5.take
Take(n)返回一个包含数据集中前n个元素的数组, 当前该操作不能并行。
6.takeSample
takeSample(withReplacement,num, [seed])返回包含随机的num个元素的数组,和Sample不同,takeSample 是行动操作,所以返回 的是数组而不是RDD , 其中第一个参数withReplacement是抽样时是否放回,第二个参数num会精确指定抽样数,而不是比例
7.takeOrdered
takeOrdered(n, [ordering])是返回包含随机的n个元素的数组,按照顺序输出
8.saveAsTextFile
把数据集中的元素写到一个文本文件,Spark会对每个元素调用toString方法来把每个元素存成文本文件的一行。
9.countByKey
对于(K, V)类型的RDD. 返回一个(K, Int)的map, Int为K的个数
10.foreach
foreach(func)是对数据集中的每个元素都执行func函数.