RDD的创建


看官网:

http://spark.apache.org/docs/latest/rdd-programming-guide.html#overview

在这里插入图片描述
创建RDD有两种方式:
①并行化一个存在的集合,把一个存在的集合转化为一个RDD。这种在测试或者造数据的时候用的比较多。
②引用一个外部存储系统的数据集,共享的文件系统,比如 HDFS, HBase,或者任何支持 Hadoop InputFormat这种格式的都可以。这种生产上面用的比较多。

创建RDD方式一:Parallelized Collections

在这里插入图片描述
在这里插入图片描述
下面以./spark-shell --master local[1] 这个启动spark-shell

scala> val data = Array(1,2,3,4,5)
data: Array[Int] = Array(1, 2, 3, 4, 5)

scala> val disData = sc.parallelize(data)   
disData: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:26
//这样就把一个数组这个集合转换成了一个RDD了
scala> disData.collect                            //①
res1: Array[Int] = Array(1, 2, 3, 4, 5)

scala> disData.reduce((a, b) => a + b)     //②
res4: Int = 15

scala> val disData2  = sc.parallelize(data,5)       //③
disData2: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[1] at parallelize at <console>:26

scala> disData2.collect                                //④
res3: Array[Int] = Array(1, 2, 3, 4, 5)

下面看一下web UI界面:
在这里插入图片描述
上图里的 Tasks (for all stages): Succeeded/Total ,task数目 1和5 是怎么来的?
以./spark-shell --master local[1] 这个启动spark-shell,就是1个core,上图里都是1,如果./spark-shell --master local[2] 这样启动的话,上图里的1就会变成2。
另外,val disData2 = sc.parallelize(data,5) ,这个单独指定了5,所以后面对这个RDD操作的话,就变成了5。
对于上面的集合来说,一个重要的参数,partition的数量,会把你的数据集给拆分成你的partition的数量。比如val disData2 = sc.parallelize(data,5),它会把disData2 这个数据集拆分成5个partition。在spark中,一个task对应一个partition,task的数量就是等于partition的数量。 Spark will run one task for each partition of the cluster.那么5个partition就会给你分配5个task。
典型的,你的集群上,每个CPU分2-4个partition。因为如果一个core对应一个task,那么很多场景下,会出现你的core处在空闲状态。2-4个partition,前面跑完了,后面还能跟上,不会产生过多的浪费。正常情况下,spark会在你的集群上尝试自动设置partition的数量。比如如果你的集群是HDFS,那么spark会自动判断,比如你的文件小于一个block大小,它会设置成一个partition,如果文件比一个block大,它会设成2个等。当然你也可以通过第二个参数来自己去设置,比如sc.parallelize(data, 10)。这个也是一个调优的点, some places in the code use the term slices (a synonym for partitions) to maintain backward compatibility。task太多的话会容易产生小文件,比较头疼,还要去合并,所以需要去调优。
另外一点需要注意的时候,上面你在创建RDD的时候是不会触发task的,只有碰到action的时候才会触发task。

创建RDD方式二:External Datasets

工作中大概95%都是这种方式创建。

在这里插入图片描述
Spark能够从任何存储上来创建分布式数据集,这个存储是支持Hadoop,包括本地文件系统、HDFS、Cassandra、HBase、Amazon S3等,这些存储上面的文件,它都能都通过spark来创建过来。spark 支持 text files, SequenceFiles, and any other Hadoop InputFormat。
Text file RDDs可以被创建,用SparkContext里的 textFile方法创建。
textFile方法 Read a text file from HDFS,a local file system (available on all nodes本地的话要保证所有的节点上面都有这个文件,因为分布式的,你运行任务的时候,你不知道它会把任务分配到哪个节点来运行,如果是HDFS,就不需要了),or any Hadoop-supported file system URI, and return it as an RDD of Strings。
textFile这个方法,会对这个文件,接收一个URI,然后读取它,读成一个集合,一行一行的。

scala> val distFile = sc.textFile("file:///home/hadoop/data/emp.txt")
distFile: org.apache.spark.rdd.RDD[String] = file:///home/hadoop/data/emp.txt MapPartitionsRDD[3] at textFile at <console>:24

scala> distFile.collect
res4: Array[String] = Array(7369        SMITH   CLERK   7902    1980-12-17      800.00          20, 7499        ALLEN   SALESMAN 7698    1981-2-20       1600.00 300.00  30, 7521        WARD    SALESMAN        7698    1981-2-22       1250.00 500.00   30, 7566        JONES   MANAGER 7839    1981-4-2        2975.00         20, 7654        MARTIN  SALESMAN        7698     1981-9-28       1250.00 1400.00 30, 7698        BLAKE   MANAGER 7839    1981-5-1        2850.00         30, 7782CLARK    MANAGER 7839    1981-6-9        2450.00         10, 7788        SCOTT   ANALYST 7566    1987-4-19       3000.00 20, 7839 KING    PRESIDENT               1981-11-17      5000.00         10, 7844        TURNER  SALESMAN        7698    1981-9-8 1500.00 0.00    30, 7876        ADAMS   CLERK   7788    1987-5-23       1100.00         20, 7900        JAMES   CLERK    7698    1981-12-3       950.00          30, 7902        FORD    ANALYST 7566    1981-12-3       3000.00         20, 7934 MILLER  CLERK   7782    1982-1-23       1300.00         10, "8888       HIVE    PROGRAM 7839    1988-1-23       10300.00         ")

scala> distFile.map(s => s.length).reduce((a, b) => a + b)
res5: Int = 686

distFile: org.apache.spark.rdd.RDD[String] 可以看出它的返回值是String。
那么从上面可以看出,spark就用本地的文件 file:///home/hadoop/data/emp.txt 创建了一个RDD distFile 。
如果是用HDFS上的文件进行创建的话,地址这样写:hdfs://ip地址:8020/emp.txt

RDD创建注意事项

在这里插入图片描述
Some notes on reading files with Spark:
①local path:如果用本地文件系统的文件路径,那么这个文件必须以相同的路径在各个节点之上能够被访问到,如果一个master,100个worker,那么就要把这个文件放到这100个worker上面。要么把文件拷贝到所有的worker上面,这种不建议,太麻烦,或者去挂载一个文件系统。
②所有的spark的基于input方法的文件,包括textFile文件,都支持目录、压缩文件、通配符。比如上面的如果有很多文件在一个文件夹里,可以这样val distFile = sc.textFile(“file:///home/hadoop/data”) 其中data是个文件夹。
③The textFile method also takes an optional second argument for controlling the number of partitions of the file. By default, Spark creates one partition for each block of the file。对于textFile 方法,你可以指定第二个参数,来控制文件partitions 的数量。就像上面的5一样。
除了text files格式,Spark’s Scala API还支持其它数据格式。比如:
④SparkContext.wholeTextFiles lets you read a directory containing multiple small text files。读取含有多个text 文件的目录,以键值对的方式返回,键值对的key是文件名,value是内容。跟text files做对比,返回值是不一样的。
⑤对于SequenceFiles,使用的是SparkContext’s sequenceFile[K, V]方法,给定它的key和value,key从Hadoop的SequenceFiles文件得到一个RDD。
⑥For other Hadoop InputFormats, you can use the SparkContext.hadoopRDD method, which takes an arbitrary JobConf and input format class, key class and value class.
⑦RDD.saveAsObjectFile and SparkContext.objectFile support saving an RDD in a simple format consisting of serialized Java objects. While this is not as efficient as specialized formats like Avro, it offers an easy way to save any RDD.你也可以把你的RDD保存到一个地方。

用spark读取SequenceFile文件。

猜你喜欢

转载自blog.csdn.net/liweihope/article/details/90544597