RDD概念

RDD(Resilient Distributed Dataset)是Spark的基础数据抽象,它是一个不可变、可分区的弹性分布式数据集,支持高效容错、位置感知调度和数据共享。RDD通过转换和行动操作进行操作,转换操作产生新的RDD而不修改原始数据,行动操作触发计算并返回结果。RDD的血缘关系使得数据丢失时可以通过重算恢复,同时支持缓存和检查点以提高性能。RDD的创建可以来自Hadoop文件系统、Scala集合或现有RDD的转换,常用操作包括map、filter、reduceByKey等。RDD的优化包括分区策略、缓存策略和错误恢复机制,确保高效并行计算。
摘要由CSDN通过智能技术生成

1 RDD的由来
RDD是Spark的基石,是实现Spark数据处理的核心抽象。那么RDD为什么会产生呢?
Hadoop的MapReduce是一种基于数据集的工作模式,面向数据,这种工作模式一般是从存储上加载数据集,然后
操作数据集,最后写入物理存储设备。数据更多面临的是一次性处理。
MR的这种方式对数据领域两种常见的操作不是很高效。第一种是迭代式的算法。比如机器学习中ALS、凸优化梯度
下降等。这些都需要基于数据集或者数据集的衍生数据反复查询反复操作。MR这种模式不太合适,即使多MR串行
处理,性能和时间也是一个问题。数据的共享依赖于磁盘。另外一种是交互式数据挖掘,MR显然不擅长。
MR中的迭代:
Spark中的迭代:
我们需要一个效率非常快,且能够支持迭代计算和有效数据共享的模型,Spark应运而生。RDD是基于工作集的工
作模式,更多的是面向工作流。
但是无论是MR还是RDD都应该具有类似位置感知、容错和负载均衡等特性。
2 RDD概念
RDD(Resilient Distributed Dataset)是一个弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可
变、可分区、里面的元素可并行计算的集合。
RDD具有数据流模型的特点:自动容错、位置感知性调度和可伸缩性。RDD允许用户在执行多个查询时显式地将工
作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度。
q1 弹性的含义

  1. 自动进行内存和磁盘数据存储的切换
    Spark优先把数据放到内存中,如果内存放不下,就会放到磁盘里面,程序进行自动的存储切换
  2. 基于血统的高效容错机制
    在RDD进行转换和动作的时候,会形成RDD的Lineage依赖链,当某一个RDD失效的时候,可以通过重新计算上游
    的RDD来重新生成丢失的RDD数据。
  3. Task如果失败会自动进行特定次数的重试
    RDD的计算任务如果运行失败,会自动进行任务的重新计算,默认次数是4次。
  4. Stage如果失败会自动进行特定次数的重试
    如果Job的某个Stage阶段计算失败,框架也会自动进行任务的重新计算,默认次数也是4次。
  5. Checkpoint和Persist可主动或被动触发
    RDD可以通过Persist持久化将RDD缓存到内存或者磁盘,当再次用到该RDD时直接读取就行。也可以将RDD进行
    检查点,检查点会将数据存储在HDFS中,该RDD的所有父RDD依赖都会被移除。
  6. 数据调度弹性
    Spark把这个JOB执行模型抽象为通用的有向无环图DAG,可以将多Stage的任务串联或并行执行,调度引擎自动处
    理Stage的失败以及Task的失败。
  7. 数据分片的高度弹性
    可以根据业务的特征,动态调整数据分片的个数,提升整体的应用执行效率。
    q2 RDD从哪来
    RDD 可以从一个 Hadoop 文件系统(或者任何其它 Hadoop 支持的文件系统),或者一个在 driver program(驱
    动程序)中已存在的 Scala 集合,以及通过 transforming(转换)来创建一个 RDD。用户为了让它在整个并行操
    作中更高效的重用,也许会让 Spark persist(持久化)一个 RDD 到内存中。最后,RDD 会自动的从节点故障中恢
    复。
    RDD支持两种操作:转化操作和行动操作。RDD 的转化操作是返回一个新的 RDD的操作,比如 map()和 filter(),而
    行动操作则是向驱动器程序返回结果或把结果写入外部系统的操作。比如 count() 和 first()。 Spark采用惰性计算
    模式,RDD只有第一次在一个行动操作中用到时,才会真正计算。Spark可以优化整个计算过程。默认情况下,
    Spark 的 RDD 会在你每次对它们进行行动操作时重新计算。如果想在多个行动操作中重用同一个 RDD,可以使用
    RDD.persist() 让 Spark 把这个 RDD 缓存下来。
    RDD里并不真正存储数据,对RDD进行操作,是在driver端转换成task,然后下发到Executor,将计算分散到多台
    集群上运行。
    RDD相当于数据的一个代理,对代理进行操作,代理隔离了细节,使分布式编程类似于单机程序,无需关心任务调
    度,容错等。
    spark提供了一个抽象叫RDD,它是集群上跨节点的元素集合,可以并行执行;
    RDD可以通过Hadoop文件(或者其他Hadoop支持的文件系统)或者存在于驱动程序上的一个已知 的scala集合创
    建,并进行转换;
    用户可以把RDD持久化到内存,在并行计算中高效实用;
    RDD具有容错能力。
    用户可以控制 RDDs 的两个方面:数据存储和分区.对于需要复用的 RDD, 用户可以明确的选择一个数据存储策略
    (比如内存缓存). 他们也可以基于一个元素的 key 来为 RDD 所有的元素在机器节点间进行数据分区, 这样非常利
    于数据分布优化, 比如给两个数据集进行相同的 hash 分区, 然后进行 join, 可以提高 join 的性能.
    通过调用 RDDs 的 persist 方法来缓存后续需要复用的 RDDs. Spark 默认是将缓存数据放在内存中, 但是如果内存
    不足的话则会写入到磁盘中. 用户可以通过 persist 的参数来调整缓存策略, 比如只将数据存储在磁盘中或者复制备
    份数据到多台机器. 最后, 用户可以为每一个 RDDs 的缓存设置优先级, 以达到哪个在内存中的 RDDs 应该首先写道
    磁盘中。
    3 RDD属性
    RDD源码里有关RDD的属性
    1)一组分片(Partition),即数据集的基本组成单位。对于RDD来说,每个分片都会被一个计算任务处理,并决
    定并行计算的粒度。用户可以在创建RDD时指定RDD的分片个数,如果没有指定,那么就会采用默认值。默认值就
    是程序所分配到的CPUCore的数目。
    2)一个计算每个分区的函数。Spark中RDD的计算是以分片为单位的,每个RDD都会实现compute函数以达到这
    个目的。compute函数会对迭代器进行复合,不需要保存每次计算的结果。
    3)RDD之间的依赖关系。RDD的每次转换都会生成一个新的RDD,所以RDD之间就会形成类似于流水线一样的前
    后依赖关系。在部分分区数据丢失时,Spark可以通过这个依赖关系重新计算丢失的分区数据,而不是对RDD的所
    有分区进行重新计算。
    4)一个Partitioner,即RDD的分片函数。当前Spark中实现了两种类型的分片函数,一个是基于哈希的
    HashPartitioner,另外一个是基于范围的RangePartitioner。只有对于key-value的RDD,才会有Partitioner,非
    key-value的RDD的Parititioner的值是None。Partitioner函数不但决定了RDD本身的分片数量,也决定了parent
    RDD Shuffle输出时的分片数量。
    5)一个列表,存储存取每个Partition的优先位置(preferred location)。对于一个HDFS文件来说,这个列表保
    存的就是每个Partition所在的块的位置。按照“移动数据不如移动计算”的理念,Spark在进行任务调度的时候,会
    尽可能地将计算任务分配到其所要处理数据块的存储位置。
    4 RDD特点
    RDD表示只读的分区的数据集,对RDD进行改动,只能通过RDD的转换操作,由一个RDD得到一个新的RDD,新
    的RDD包含了从其他RDD衍生所必需的信息。RDDs之间存在依赖,RDD的执行是按照血缘关系延时计算的。如果
    血缘关系较长,可以通过持久化RDD来切断血缘关系。
    分区
    RDD逻辑上是分区的,每个分区的数据是抽象存在的,计算的时候会通过一个compute函数得到每个分区的数
    据。如果RDD是通过已有的文件系统构建,则compute函数是读取指定文件系统中的数据,如果RDD是通过其他
    RDD转换而来,则compute函数是执行转换逻辑将其他RDD的数据进行转换。
    只读
    如下图所示,RDD是只读的,要想改变RDD中的数据,只能在现有的RDD基础上创建新的RDD。
    由一个RDD转换到另一个RDD,可以通过丰富的操作算子实现,不再像MapReduce那样只能写map和reduce了,
    如下图所示。
    RDD的操作算子包括两类,一类叫做transformations,它是用来将RDD进行转化,构建RDD的血缘关系;另一类
    叫做actions,它是用来触发RDD的计算,得到RDD的相关计算结果或者将RDD保存的文件系统中。下图是RDD所
    支持的操作算子列表。
    依赖
    RDDs通过操作算子进行转换,转换得到的新RDD包含了从其他RDDs衍生所必需的信息,RDDs之间维护着这种血
    缘关系,也称之为依赖。如下图所示,依赖包括两种,一种是窄依赖,RDDs之间分区是一一对应的,另一种是宽
    依赖,下游RDD的每个分区与上游RDD(也称之为父RDD)的每个分区都有关,是多对多的关系。
    通过RDDs之间的这种依赖关系,一个任务流可以描述为DAG(有向无环图),如下图所示,在实际执行过程中宽依
    赖对应于Shuffle(图中的reduceByKey和join),窄依赖中的所有转换操作可以通过类似于管道的方式一气呵成执行
    (图中map和union可以一起执行)。
    缓存
    如果在应用程序中多次使用同一个RDD,可以将该RDD缓存起来,该RDD只有在第一次计算的时候会根据血缘关
    系得到分区的数据,在后续其他地方用到该RDD的时候,会直接从缓存处取而不用再根据血缘关系计算,这样就加
    速后期的重用。如下图所示,RDD-1经过一系列的转换后得到RDD-n并保存到hdfs,RDD-1在这一过程中会有个中
    间结果,如果将其缓存到内存,那么在随后的RDD-1转换到RDD-m这一过程中,就不会计算其之前的RDD-0了。
    checkpoint
    虽然RDD的血缘关系天然地可以实现容错,当RDD的某个分区数据失败或丢失,可以通过血缘关系重建。但是对
    于长时间迭代型应用来说,随着迭代的进行,RDDs之间的血缘关系会越来越长,一旦在后续迭代过程中出错,则
    需要通过非常长的血缘关系去重建,势必影响性能。为此,RDD支持checkpoint将数据保存到持久化的存储中,这
    样就可以切断之前的血缘关系,因为checkpoint后的RDD不需要知道它的父RDDs了,它可以从checkpoint处拿到
    数据。
    给定一个RDD我们至少可以知道如下几点信息:
    1、分区数以及分区方式;
    2、由父RDDs衍生而来的相关依赖信息;
    5、计算每个分区的数据,计算步骤为:
    1)如果被缓存,则从缓存中取的分区的数据;
    2)如果被checkpoint,则从checkpoint处恢复数据;
    3)根据血缘关系计算分区的数据。
    5 创建RDD
    1)由一个Scala集合或数组以并行化的方式创建。
    一般用来测试或者实验
    RDD一旦创建,分布式的数据集就可以执行并行计算
    RDD创建的过程中,一个重要参数是把数据集切分的分区数。Spark针对集群中的每一个分区执行一个任务
    (task),一般,集群中每一个CPU分配2-4个分区,Spark会基于集群自动设置分区数目,但是,也可以手动指
    定,比如:
    val rdd1 =sc.parallelize(Array(1,2,3,4,5,6,7,8))
    rdd1.reduce((a,b)=>a+b)
    sc.parallelize(data, 10)
    注意:通过一个集合创建一个RDD,也可以使用
    2)由外部存储系统的数据集创建,包括本地的文件系统,还有所有Hadoop支持的数据集,比如HDFS、
    Cassandra、HDFS, Cassandra, HBase, Amazon S3等,Spark支持文本文件、序列文件(SequenceFiles are flat
    files consisting of binary key/value pairs.“Flat"which means it has no structure for indexing and there are
    usually no structural relationships between the records. )以及任何Hadoop支持的数据集。
    使用Spark读取文件需要注意的点:
    如果读取的是本地文件,该文件必须是worker节点可以存取的,通过拷贝文件到所有的worker节点或者使用
    基于挂载的共享文件系统;
    spark中所有参数是文件的方法,包括文本文件,都支持目录、压缩文件和通配符文件,比如可以使用
    textFile 方法也有一个可选参数控制文件的分区数量,默认情况下,Spark文件的每一个block生成一个
    partition分区(HDFS默认快大小为128MB),但是也可以传入一个更大的值获取更多的分区,但是无法获取
    少于block个数的分区个数。
    3)使用已有的RDD&#x
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值