文章目录
RDD创建
从文件系统中加载数据创建RDD:
-
Spark采用textFile() 方法来从文件系统中加载数据创建RDD
-
方法把文件的URI作为参数,这个URI可以是:
1) 本地文件系统的地址 2) 或者是分布式文件系统HDFS的地址 3) 或者是Amazon S3的地址等
通过并行集合(数组)创建RDD:
可以调用SparkContext的parallelize方法,在Driver中一个已经存在的集合(数组)上创建。
val array = Array(1,2,3,4,5)
val rdd = sc.parallelize(array)
RDD操作
转换操作
- 对于RDD而言,每一个转换操作都会产生不同的RDD,供一个操作使用。
- 转换到的RDD是惰性求值的。不发生真正的计算。
基本的转化操作
函数名 | 目的 |
---|---|
map() | 将函数应用于RDD中的每个元素,将返回值构成新的RDD |
flatmap() | 将函数应用于RDD中的每个元素,将返回的迭代器的内容构成新的RDD,通常用来切分单词 |
filter() | 返回一个通过传给filter()的函数的元素组成RDD |
distinct() | 去重 |
sample(withReplacement, fraction, [seed] | 对RDD采样,以及是否替换 |
union() | 生成一个包含两个RDD中所有元素的RDD |
intersection() | 求两个RDD共同的元素的RDD |
subtract() | 移除一个RDD中的内容 |
cartesian() | 于另一个RDD的笛卡尔积 |
groupByKey | 应用于(K, b)键值对的数据集时,返回一个新的(K, Iterable)形式的数据集 |
reduceByKey(func) | 应用于(K, V)键值对的数据集时,返回一个新的(K, V)形式的数据集,其中的每个值是将每个Key传递到函数func中进行聚合 |
行动操作
真正触发计算的地方。
函数名 | 目的 |
---|---|
collect() | 返回RDD中的所有元素 |
count() | RDD中的元素个数 |
countByValue() | 各元素在RDD中出现的次数 |
take(num) | 从RDD中返回num个元素 |
top(num) | 从RDD中返回最前面的num个元素 |
takeOrdered(num) (ordering) | 从RDD中按照提供的顺序返回最前面的num个元素 |
takeSample(withRepalcement, num, [seed]) | 从RDD中返回任意一些元素 |
reduce(func) | 并行整合RDD中所有的整数 |
fold(zero)(func) | 和reduce()一样,但是需要提供初始值 |
aggreagte(zeroValue)(seqOp, comOp) | 和Reduce()相似,但是通常返回不同类型的函数 |
foreach(func) | 对RDD中的每个元素使用给定的函数 |
注意点:
- collect() 要求所有数据都必须能一同放入单台机器的内存中。
- take(n) 尝试只访问尽量少的分区,因此会得到一个不均衡的集合,返回元素的顺序与预期不一致。
- top() 可以通过提供自己的比较函数,来提取前几个元素
- foreach() 不将任何结果返回到驱动程序中,把数据发送到一个网络服务器中或数据库中。
持久化
spark中,RDD采用惰性求值得机制,每次遇到行动操作,都会从头开始执行计算,每次调用行动操作,都会触发一次从头开始的计算,这对于迭代操作而言,代价是很大的,迭代计算经常需要多次重复使用同一组数据。
可以通过持久化(缓存)机制避免这种重复计算的开销。
可以使用persist()方法对一个RDD标记为持久化。
persist()的圆括号内中包含的是持久化级别参数。
- persist(MEMORY_ONLY):表示将RDD作为反序列化的对象存储于JVM中,如果内存不足,就要按照LRU原则替换缓存中的内存。
- persist(MEMORY_AND_DISK)表示将RDD作为反序列化的对象存储在JVM中,如果内存不足,超出的分区将会被存放在硬盘上。
- 可以使用unpersist()方法手动地把持久化的RDD从缓存中移除。
- 一般而言,使用cache()方法时,会调用persist(MEMORY_ONLY)
分区
分区原则:
RDD分区的一个分区原则是使得分区的个数尽量等于集群中的CPU核心数目。
默认分区数目:
对于不同的Spark部署模式而言,都可以通过设置spark.default.parallelism这个参数的值,来配置默认的分区数目。
手动设置分区:
- 创建RDD时:在调用textFile和parallelize方法时候手动指定分区个数,sc.textFile(path, partitionNum)
- 通过转换操作得到RDD时:直接调用repatition方法即可(RDD数据量在经过转换操作后变小,无需过多的分区)
打印元素:
- 单机模式下打印输出到屏幕上:rdd.foreach(println)或rdd.map(println)
- 为了能够把所有worker节点上的打印输出信息也显示到Driver Program中,可以使用collect()方法:rdd.collect().foreach(println)。但是如果数据量过大,可能会导致内存溢出,采用rdd.take(100).foreach(println)。
Pair RDD的创建
从文件中加载
使用map()函数创建:
val lines = sc.textFile("file:///usr/local/spark/mycode/pairrdd/word.txt")
val pairRDD = lines.flatMap(line => line.split(" ").map(word => (word.1))
pairRDD.foreach(println)
通过并行集合(数组)创建RDD
val list =