RDD分布式数据集
RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,
是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合。RPartition,数据集的基本组成单位。对于RDD来说,每个分片都会被一个计算任务处理,
并决定并行计算的粒度。RDD的分配个数默认为CPU核心数。 (rdd.partitionBy(20, hash_domain) # Create 20 partitions)Spark中RDD的计算是以分片为单位的,每个RDD都会实现compute函数并且对迭代器进行复合以达到这个目的。
RDD的每次转换都会生成一个新的RDD,所以RDD之间就会形成类似于流水线一样的前后依赖关系。
在部分分区数据丢失时,Spark可以通过这个依赖关系重新计算丢失的分区数据,而不是对RDD的所有分区进行重新计算。当前Spark中实现了两种类型的分片函数,一个是基于哈希的HashPartitioner,
另外一个是基于范围的RangePartitioner。只有对于于key-value的RDD,才会有Partitioner,
非key-value的RDD的Parititioner的值是None。Partitioner函数不但决定了RDD本身的分片数量,也决定了parent RDD
Shuffle输出时的分片数量。对于一个HDFS文件来说,这个列表保存的就是每个Partition所在的块的位置。
按照“移动数据不如移动计算”的理念,Spark在进行任务调度的时候,
会尽可能地将计算任务分配到其所要处理数据块的存储位置。
RDD编程(python)
RDD Basics
# 读取本地文件内容 lines = sc.textFile("README.md") # 读取HDFS文件内容 lines = sc.textFile("hdfs://xxxx/xx/xxx") # 根据数组写入Spark lines = sc.parallelize(["pandas", "i like pandas"])
map()
参数是函数,函数应用于RDD每一个元素,返回值是新的RDD newRDD = RDD.map(lambda x:x[0]) RDD --> ["123","123","123","123","123"] newRDD -> ["1","1","1","1","1"] 其中匿名函数 lamdbda 等价于 def func(x): return x[0] newRDD = RDD.map(func)
flatMap()
参数是函数,函数应用于RDD每一个元素,将元素数据进行拆分,变成迭代器,返回值是新的RDD newRDD = RDD.flatMap(lambda x:x.split("2")) RDD --> ["123","123"] newRDD -> ["1","3","1","3"]
filter()
参数是函数,函数会过滤掉不符合条件的元素,返回值是新的RDD newRDD = RDD.filter(lambda x: "12" in x ) RDD --> ["12","123","234"] newRDD -> ["12","123"]
distinct()
没有参数,将RDD里的元素进行去重操作 newRDD = RDD.distinct() RDD --> ["12","12","234"] newRDD -> ["12","234"]
union()
参数是RDD,生成包含两个RDD 所有 元素的新RDD newRDD = RDD.distinct(oldRDD) oldRDD --> ["12","12","234"] RDD --> ["12","12","234"] newRDD -> ["12","12","234","12","12","234"]
intersection()
参数是RDD,求出两个RDD的共同元素 newRDD = RDD.intersection(oldRDD) oldRDD --> ["12","12","234","2234"] RDD --> ["12","12","234","5687"] newRDD --> ["12","12","234"]
subtract()
参数是RDD,将原RDD里和参数RDD里相同的元素去掉 newRDD = RDD.subtract(oldRDD) oldRDD --> ["12","12","234","2234"] RDD --> ["12","12","234","5687"] newRDD --> ["2234","5687"]
cartesian()
参数是RDD,求两个RDD的笛卡儿积 newRDD = RDD.cartesian(oldRDD) RDD --> [a, b] oldRDD --> [0, 1, 2] newRDD --> [(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)]
action
- collect(),返回RDD所有元素
- count(),RDD里元素个数
- top(num),取最前几个
- take(num),取最后几个
- takeOrdered(num)(ordering),取排序后的前几个
- countByValue(),各元素在RDD中出现次数
reduce()
并行整合所有RDD数据,例如连乘操作 参数是函数 newRDD = RDD.reduce(lambda x , y : x * y ) RDD --> [1,2,3,4,5] newRDD --> 120
fold(0)(func),和reduce功能一样,不过fold带有初始值
- aggregate(0)(seqOp,combop),和reduce功能一样,但是返回的RDD数据类型和原RDD不一样
- foreach(func)对RDD每个元素都是使用特定函数
Pair RDDs (key/value)
Transformations on one pair RDD
reduceByKey(func)
并行整合每一个key的数据 例如将每一key的累加和 newRDD = RDD.reduceByKey(lambda x , y : x * y ) RDD --> {(1, 2), (3, 4), (3, 6)} nweRDD --> {(1,2), (3,10)}
groupByKey()
根据key进行分组 nweRDD = RDD.groupByKey() RDD --> {(1, 2), (3, 4), (3, 6)} nweRDD -->{(1,[2]),(3, [4,6])}
mapValues(func)
分别对每一个key 进行map 在组合在一起 newRDD = RDD.mapValues(lambda x:x+1) RDD --> {(1, 2), (3, 4), (3, 6)} nweRDD --> {(1,3), (3,5), (3,7)}
flatMapValues(func)
同上 + flatmap
keys()
newRDD = RDD.keys() RDD --> {(1, 2), (3, 4), (3, 6)} newRDD --> {1, 3,3}
value()
newRDD = RDD.value() RDD --> {(1, 2), (3, 4), (3, 6)} newRDD --> {2, 4 , 6}
sortByKey()
根据key值排序 newRDD = RDD.sortByKey() RDD --> {(1, 2), (3, 4), (3, 6)} newRDD -->{(1,2), (3,4), (3,6)}
Transformations on two pair RDD
subtractByKey(other : RDD)
根据移除RDD中 oldRDDKey 的值相同的 newRDD = RDD.subtractByKey(oldRDD) RDD --> {(1, 2), (3, 4), (3, 6)} oldRDD --> {(3, 9)} newRDD --> {(1, 2)}
join(other : RDD)
执行内部连接 和sql链接操作类似 newRDD = RDD.join(oldRDD) RDD --> {(1, 2), (3, 4), (3, 6)} oldRDD --> {(3, 9)} newRDD --> {(3, (4, 9)), (3,(6, 9))}
rightOuterJoin
右边链接左边 some在左 newRDD = RDD.rightOuterJoin(oldRDD) RDD --> {(1, 2), (3, 4), (3, 6)} oldRDD --> {(3, 9)} newRDD --> {(3,(Some(4),9)),(3,(Some(6),9))}
leftOuterJoin
左边链接右边 some在右 newRDD = RDD.rightOuterJoin(oldRDD) RDD --> {(1, 2), (3, 4), (3, 6)} oldRDD --> {(3, 9)} newRDD --> {(1,(2,None)), (3,(4,Some(9))), (3,(6,Some(9)))}
cogroup
将两个rdd进行组合 共享key值 newRDD = RDD.rightOuterJoin(oldRDD) RDD --> {(1, 2), (3, 4), (3, 6)} oldRDD --> {(3, 9)} newRDD --> {(1,([2],[])), (3,([4, 6],[9]))}
Actions Available on Pair RDDs
- countByKey()
collectAsMap()
map = RDD.collectAsMap() RDD --> {(1, 2), (3, 4), (3, 6)} map --> Map{(1, 2), (3,4), (3, 6)}
lookup(key)
返回 key 对应的所有value values = RDD.lookup(3) RDD --> {(1, 2), (3, 4), (3, 6)} values --> [4,6]