定义
RDD是弹性分布式数据集(Resilient Distributed Dataset), RDD 其实就是分布式的元素集合。就像List,Array,Set,Map集合。在 Spark 中,对数据的所有操作不外乎创建 RDD、 转化已有 RDD 以及调用 RDD 操作进行求值。而在这一切背后, Spark 会自动将RDD中的数据分发到集群上,并将操作并行化执行。
用户可以使用两种方法创建 RDD: 读取一个外部数据集,或在驱动器程序里分发驱动器程序中的对象集合(比如 list 和 set) ;
RDD是只读的。一旦生成就不能修改;
RDD可以通过重新计算得到;
举个栗子,读取文件ReadME.md数据
》lines = sc.textFile("README.md")
》pythonLines = lines.filter(lambda line: "Python" in line)
Spark 只会惰性计算这些 RDD ,也就是它们只有第一次在一个行动操作中用到时,才会真正计算 。这样的好处是上面例子我们以一个文本文件定义了数据,然后把其中包含 Python 的行筛选出来。如果 Spark 在我们运行 lines= sc.textFile(…) 时就把文件中所有的行都读取并存储起来, 就会消耗很多存储空间,而我们马上就要筛选掉其中的很多数据。相反, 一旦 Spark 了解了完整的转化操作链之后,它就可以只计算求结果时真正需要的数据。事实上,在行动操作 first() 中, Spark 只需要扫描文件直到找到第一个匹配的行为止,而不需要读取整个文件 。默认情况下, Spark 的 RDD 会在你每次对它们进行行动操作时重新计算。如果想在多个行动操作中重用同一个 RDD, 可以使用 RDD.persist() 让 Spark 把这个 RDD 缓存下来
转换(Transformation)操作
每次转换操作都会生成一个新的RDD。转化出来的 RDD 是惰性求值的,只有在行动操作中用到这些 RDD 时才会被计算 。
转换 | 说明 | |
---|---|---|
map | 数据集中的每条元素经过函数转换后形成一个新的分布式数据集 | |
filter | 过滤作用,选取数据集中让函数返回为true的元素,形成一个新的数据集 | |
flatMap | 类似于map,但每个输入项可以被映射到0个或更多的输出项 | |
mapParttions | 类似于map,但单独运行在RDD每个分区 | |
union | 返回一个由原数据集和参数联合而成的心得数据集 | |
distinct | 返回一个数据集去重过后的新的数据集 |
说明
map:
第一次看map的操作,半天没有看懂,原因是在java中map是一个k,v键值对集合。就搞不懂这个是怎么 回事看了很久才明白这个跟java中的map不是一回事。map输入是一个RDD,输出也是一个RDD,RDD数不会变。
flatMap:
是一个RDD转换函数,接受一个函数作为输入,对当前RDD所有成员电泳输入的函数,并返回一个新的RDD,flatMap对每个输入的RDD,返回的是一个集合,集合里面的成员会被展开,一个输入可以对应多个输出。比如对“# Apache Spark”进行空格拆分,返回的是一个数组,包含3个成员,“#”,“Apache”,“Spark”,最终3个成员会成为RDD直接成员。
假设有N个元素,有M个分区,那么map函数将被调用N次,而mapParttions被调用M次,一次函数处理一个分区。
行动(Action)操作
对数据转换后进行行动操作,输出结果不再是RDD,返回给Driver程序
操作 | 说明 | |
---|---|---|
reduce | 对RDD成员使用进行reduce操作,返回结果只有一个值 | |
collect | 将RDD读取到Driver程序,类型是一个Array,一般要求RDD不能太大 | |
count | 返回RDD成员数 | |
first | 返回RDD一个成员 | |
take(n) | 返回前n个成员 | |
saveAsTextFile(path) | 将RDD转换为文本内容并保存到path路径下,可能有多个文件,path可以为具体路径或HDFS地址 | |
saveAsSequenceFile(path) | 与saveAsTextFile类似,但是已SequenceFile格式保存 | |
countBykey | 仅适用于(k,v)类型,对key计算,返回(k,int) | |
foreach(func) | 对RDD中的每个成员执行回调func,没有返回值,常用于更新计算器或输出数据至外部存储系统。这里需要注意变量的作用域 |
说明:
collect:
可以用来获取整个 RDD 中的数据。如果你的程序把 RDD 筛选到一个很小的规模,并且你想在本地处理
这些数据时, 就可以使用它。只有当你的整个数据集能在单台机器的内存中放得下时,才能使用 collect(),因此, collect() 不能用在大规模数据集上 。