Spark的基本数据结构RDD介绍

来源:互联网 发布:java微信 编辑:程序博客网 时间:2024/05/19 15:18

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.可选,如果是(KeyValue)型的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().

            sparkcache是容错的,如果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  //离堆

 

 

RDDtransformation函数和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的个数.


0 0