目录
Spark编程核心—2,RDD详解
写一个spark应用程序的流程:
1、 加载数据集(获得RDD)
2、 使用transformation算子对RDD进行操作
Transformation算子是一系列懒执行的函数
3、 使用actions算子触发执行
Transformation算子对RDD的操作会先被记录,当actions算子触发后才会真正执行
伪代码:
子
lines = sc.textFile(“hdfs://master:9000/aaa.txt”)//加载数据集
rdd1 = lines.map(x=>(x,1)). //transformation算子
rdd1.reduceByKey(_+_).collect().foreach(println) //最后的foreach是action算子
常见的RDD算子
Transformation算子
map(f : T => U)
将函数应用于RDD中的每一个元素,将返回值构成新的RDD
//求每个元素平方
nums = sc.parallelize(List(1,2,3,4))
squared = nums.amp(x=>x*x)
println(result.collect().mkString(,))
fliter(f : T => Bool)
返回一个由通过传给filter()的函数的元素组成的RDD
flatMap(f : T => Seq[U])
将函数应用于RDD中的每个元素,将返回的迭代器中的所有内容组成一个新RDD
val lines = sc.parallelize(List("Hello World","hi"))
val words = lines.flatMap(line=> line.split(" "))
words.first() //返回hello
sample(fraction : Float)
对RDD中的元素随机采样,且可以进行替换
groupByKey()
对RDD进行按key分组
reduceByKey()
按照指定规则合并Value
val data = seq(("a",3),("b",4),("c",5))
sc.parallelize(data).reduceByKey((x,y) => x + y)
sc.parallelize(data).reduceByKey((x,y) => x + y , 10) //自定义并行度
union()
对两个RDD取并集
rdd1.union(rdd2)
join()
对两个RDD进行内连接,输出两个RDD中都存在的键
sort(c : Comparator[K])
排序,默认升序
sortByKey()
按 key 进行排序
sortBy()
自定义排序规则
partitionBy(p : Partition[K])
对RDD进行分区,返回新RDD
distinct()
去掉重复数据
Action算子
count()
统计 RDD 中元素的个数
foreach()
遍历 RDD 中的元素
foreachPartition()
以分区为单位遍历 RDD, map 和 mapPartition 可以与它们做类比,但 map 和 mapPartitions 是 transformations 算子
collect()
把运行结果拉回到 Driver 端
take(n)
取 RDD 中的前 n 个元素
reduce()
按照指定规则聚合 RDD 中的元素
val sum = rdd.reduce(_+_)
countByKey()
统计出 KV 格式的 RDD 中相同的 K 的个数
countByValue()
统计出 RDD 中每个元素的个数
RDD中一些值得注意的点
1、缓存
为了避免对同一RDD多次计算,可以让Spark对数据持久化。当我们让Spark持久化存储一个RDD时,计算出RDD的节点会分别保存他们所求出的分区数据。
出于不同的环境,我们可以选择不同的缓存级别。Scala和Java,默认情况下persist()会把数据以序列化的形式缓存在JVM的堆空间中。当然也可以自行更改存储位置。
通过org.apache.spark.storage.StorageLevel中设定持久化级别,共有五种,也可以在末尾加上“_2”来存两份
MEMORY_ONLY 只存储在内存
MEMORY_ONLY_SER 只存在内存且序列化
MEMORY_AND_DISK 如果内存存不下就存在硬盘上
MEMORY_AND_DISK_SER 同上,存的是序列化数据
DISK_ONLY 存硬盘上
2、数据分区
分区的主要目的是减少网络IO,其次有助于并行化处理。分区处理最大的受益者是基于键的RDD,如join()、groupWith()、combineByKey()、lookup()等等
关于分区的其他概念请看我上一篇博客(诶嘿~访问量+2)
//Scala自定义分区的方式
val sc = new SparkContext(...)
val userData = sc.sequenceFile[User