1、RDD:resilient distributed dataset
弹性分布式数据集:
弹性:
RDD之间有依赖关系,使得RDD具有容错机制
分区和task设置,但是可以设置
前后算子间的分区数相同,但也可以设置,比如合并分区
分布式:
一个RDD对应很多个分区,一个分区分布在多个节点
注意:
rdd是逻辑概念,存计算逻辑,不存数据。
2、五大特性:
1、RDD是由一系列的分区组成。
2、操作一个RDD实际上操作的是RDD的所有分区。
3、RDD之间存在各种依赖关系。
4、分区器是作用在K,V格式的RDD上。(RDD内部的分区中装的是二元tuple)
5、RDD的每一个分区在计算时会选择最佳的计算位置。
3、源码:
abstract class RDD[T](
@scala.transient private var _sc : org.apache.spark.SparkContext,
private var deps : scala.Seq[org.apache.spark.Dependency[_]])
(implicit evidence$1 : scala.reflect.ClassTag[T])
extends scala.AnyRef with scala.Serializable
with org.apache.spark.internal.Logging {...}
发现:
泛型T,意味着可以包含常见的任意类型
抽象类,不能直接使用,只能使用子类
继承Serializable,RDD可以序列化
不可变集合,集合元素可以并行化地处理
4、RDD创建
A)通过已经存在的驱动程序中的集合进行创建
示例:
val data=Array(1,2,3,4)
val dis=sc.parallelize(data)
或者 val dis=sc.makeRDD(data)
注:
parallelize和makeRDD还有第二个参数,代表分区数
默认一个分区对应一个task,手动指定分区可以避免task过多,任务执行慢
spark.default.parallelism可以设置当前stage的并行度,即有几个task
slices控制分区数,这儿有一个调优点,以后说
spark设置的分区数不能过大,不然很多输出文件都是空文件。这也是一个调优点。
最佳实践:
建议一个逻辑core设置2-4个分区
B)通过引用外部存储系统中的数据集进行创建(生产常用)
外部存储系统:HDFS/HBase/任何支持hadoop InputFormat的文件系统。
因为读取文件通过MR中读取文件的那个类TextInputFormat
示例:
val dis=sc.textFile("hdfs://Linux005/input.txt")
注:
textfile有第2个参数,代表分区数
也可以执行本地路径,但要保证文件在所有节点都有
C)rdd的其他操作:
查看分区数:dis.partitions.size()
查看0号分区数据:dis.preferredLocations(dis.partitions(0))
统计大小:dis.count()
注意事项:
1、对于访问本地文件,一定要保证所有节点上都有该文件,否则就将该文件上传到hdfs上,再
通过访问hdfs上该文件进行RDD的创建。
2、所有基于spark的文件输入格式,包括textFile,都支持对于目录,压缩文件的操作,也支持
通配符。
3、textFile的第2个参数可以设置文件的分区数,默认情况下spark会为每一个block(hdfs上的
block为128MB)创建一个分区,对于较大的文件,你也可以设置更高的分区数,但是,不要
让设置的分区数小于block的数量。
4、除了textFile,spark的scala api还支持其他的几种数据格式:
SparkContext.wholeTextFiles
读取目录,并对每个文件都返回一个键值对,key为文件名称,value为文件内容。
sequenceFile(k,v)
k和v指的是文件的key和value的类型,类型必须实现了Hadoop Writable接口,比
如IntWritable和Text。
Int,String之类的原生类型。
会被隐式转换成IntWritable,Text。
基于hadoop的输入格式,可以使用SparkContext.hadoopRDD方法
RDD.saveAsObjectFile和SparkContext.objectFile支持一个简单保存RDD的方法,能简
单地保存任意类型的RDD。
5、补充从hbase读取数据
scala>import org.apache.hadoop.hbase.*
scala> val conf = HBaseConfiguration.create()
scala> conf.set(TableInputFormat.INPUT_TABLE,"lalalal")
scala> var hbaseRDD = sc.newAPIHadoopRDD(
conf,classOf[org.apache.hadoop.hbase.mapreduce.TableInputFormat],
classOf[org.apache.hadoop.hbase.io.ImmutableBytesWritable],
classOf[org.apache.hadoop.hbase.client.Result])