RDD的全称:弹性分布式数据集合,它是spark的基本数据结构,spark中的所有数据都是通过RDD的形式进行组织。
RDD是不可变的数据集合,不可变的意思是RDD中的每个分区数据是只读的。
RDD数据集是要做逻辑分区的(这里的分区类似hadoop中的逻辑切片split),每个分区可以单独在集群节点进行计算。
RDD数据集中的数据类型可以包含任何java类型、scala类型、python类型或者自定义的类型。
RDD擅长的领域:迭代式的数据处理,比如机器学习。
RDD自带的5个属性详解——
1.分区列表,Partition List。这里的分区概念类似hadoop中的split切片概念,即数据的逻辑切片
2.针对每个split(切片)的计算函数,即同一个RDD的每个切片的数据使用相同的计算函数
3.对其他rdd的依赖列表
4.可选,如果是(Key,Value)型的RDD,可以带分区类
5.可选,首选块位置列表(hdfs block location);
RDD和作业、任务之间有什么关系——
RDD提供数据,供任务处理。
通常我们把hadoop和spark结合使用,hadoop提供hdfs的分布式存储,spark处理hdfs中的数据。
当我们以sc.textFile("hdfs://path/to/file")形式生成RDD时,spark就已经算好了数据的各个切片(也叫分区),并把分区信息放在了一个列表(名单)里,这个名单就属于RDD自带的其中一个属性。所以RDD不包含实际要处理的数据,而是在RDD中的分区名单中载明切片的信息。因为数据已经在Hadoop的数据节点上了, 只要在RDD中标明分区对应的数据所在位置、偏移量、数据长度即可,就类似元数据。
RDD在被分发到每个执行计算的任务节点后,每个任务节点会根据元数据信息获取自身节点负责计算的分区数据,并把数据放到本节点的内存当中,然后对数据进行计算。每个分区由一个节点来计算,换句话说就是每个任务只计算RDD的其中一个分区。
一般我们会把数据所在的节点和spark的计算节点配成同一个主机,这样就实现了数据本地化。那么在worker节点将要运行spark的计算任务时,只需要从本地加载数据,再对数据运用spark的计算函数,就不需要从别处(例如远程主机)通过网络传输把需要计算的数据拿过来,从而避免了昂贵的网络传输成本。“宁可移动函数,也不要移动数据”。
创建RDD方式——
一、并行化一个现有集合。
二、加载外部存储文件,例如sc.textFile(“/home/tonykidkid/files/abc.txt”)会生成一个RDD
RDD的持久化——
对于一个经常被使用的RDD或者计算代价较大的RDD,需要把它缓存,以便提高处理效率。
跨操作进行RDD的内存式存储。
持久化RDD时,节点上的每个分区都会保存到内存中,以备在其他操作中进行重用。
缓存技术是迭代式计算和交互式查询的重要工具。
使用persist()和cache()进行rdd的持久化。
cache()是persist()一种简化方式,这种用法适用于只使用内存作缓存时
action第一次计算时会发生persist().
spark的cache是容错的,如果rdd的任何一个分区丢失了,都可以通过最初创建rdd的进行重新计算。
persist可以使用不同的存储级别进行持久化:
MEMORY_ONLY //只在内存中
MEMORY_AND_DISK
MEMORY_ONLY_SER //内存存储(串行化)
MEMORY_AND_DISK_SER
DISK_ONLY //只存在硬盘
MEMORY_ONLY_2 //带有副本
MEMORY_AND_DISK_2 //快速容错。
OFF_HEAP //离堆
RDD的transformation函数和action函数——
变换函数(transformation function)
会返回指向一个新RDD的指针,在RDD之间创建依赖关系。
每个RDD都有算子以及指向父RDD的指针。
RDD常用的变换函数:
map() //对每个元素进行变换,应用变换函数(T)=>V
filter() //过滤器,(T)=>Boolean
flatMap() //轧扁T => TraversableOnce[U]
mapPartitions() //可对分区进行函数处理,输入Iterator, 返回新迭代器Iterator<T> =>Iterator<U>
mapPartitionsWithIndex(func) //用法类似mapPartitions()函数(Int, Iterator<T>) => Iterator<U>
sample(withReplacement, fraction, seed) //采样.返回采样的rdd子集。withReplacement:是否多次采样. fraction:期望采样数量[0,1]
union() //类似于mysqlunion操作, 竖直连接select * frompersons where id < 10 union (select * from id persons where id > 29)
intersection //求交集,提取两个rdd中同时含有的元素。
distinct([numTasks])) //去除重复的元素。
groupByKey() //传入(K,V)返回(K,Iterable<V>) 相同key的行聚在一起
reduceByKey(*) //按key聚合
aggregateByKey(zeroValue)(seqOp, combOp,[numTasks]) //按照key进行聚合key:String U:Int = 0
sortByKey //按照指定的key排序
join(otherDataset, [numTasks]) //横向连接,(K,V).join(K,W) =>(K,(V,W))
cogroup //协分组(K,V).cogroup(K,W) =>(K,(Iterable<V>,Iterable<!--<W> -->))
cartesian(otherDataset) //笛卡尔积,RR[T] RDD[U] => RDD[(T,U)]
pipe //将rdd的元素传递给脚本或者linux终端命令,执行结果返回形成新的RDD
coalesce(numPartitions) //减少分区,只能减少不能增加
repartition //重新指定分区数,数目可增可减
repartitionAndSortWithinPartitions(partitioner) //再分区并在分区内进行排序
Redaction函数
action函数会返回单个值。
RDD常用的action函数:
collect() //收集rdd元素形成数组.
count() //统计rdd元素的个数
reduce() //聚合,返回一个值。
first //取出第一个元素take(1)
take(n) //取出范围内的数据
takeSample(withReplacement,num, [seed])
takeOrdered(n,[ordering])
saveAsTextFile(path) //保存到文件
saveAsSequenceFile(path) //保存成序列文件
saveAsObjectFile(path)(Java and Scala)
countByKey() //按照key,统计每个key下value的个数.