zoukankan      html  css  js  c++  java
  • spark_rdd 一波怼完面试官系列

    Resilient Distributed dataset , 弹性分布式数据集。

    分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现。
    RDD是Spark最核心的东西,它表示已被分区,不可变的并能够被并行操作的数据集合,不同的数据集格式对应不同的RDD实现。
    RDD必须是可序列化的。RDD可以cache到内存中,每次对RDD数据集的操作之后的结果,都可以存放到内存中,
    下一个操作可以直接从内存中输入,省去了MapReduce大量的磁盘IO操作。
    这对于迭代运算比较常见的机器学习算法, 交互式数据挖掘来说,效率提升比较大。大的集合,将所有数据都加载到内存中,方便进行多次重用。
        第一,它是分布式的,可以分布在多台机器上,进行计算。
        第二,它是弹性的,在计算处理过程中,机器的内存不够时,它会和硬盘进行数据交换,某种程度上会减低性能,但是可以确保计算得以继续进行。
    

    特性

    RDD是分布式只读且已分区集合对象。
    	这些集合是弹性的,如果数据集一部分丢失,则可以对它们进行重建。
    	具有自动容错、位置感知调度和可伸缩性,而容错性是最难实现的,大多数分布式数据集的容错性有
    	两种方式:数据检查点和记录数据的更新。对于大规模数据分析系统,数据检查点操作成本很高,
    	主要原因是大规模数据在服务器之间的传输带来的各方面的问题,相比记录数据的更新,RDD 也只支持粗粒度的转换,
    	也就是记录如何从其它 RDD 转换而来(即 Lineage),以便恢复丢失的分区。
    	
    	其特性为:
    		1数据存储结构不可变
    		2支持跨集群的分布式数据操作
    		3可对数据记录按key进行分区
    		4提供了粗粒度的转换操作
    		5数据存储在内存中,保证了低延迟性
    

    RDD的好处

    	1RDD只能从持久存储或通过Transformations操作产生,相比于分布式共享内存(DSM)可以更高效实现容错,
    								对于丢失部分数据分区只需根据它的lineage就可重新计算出来,而不需要做特定的Checkpoint。
    	2RDD的不变性,可以实现类Hadoop MapReduce的推测式执行。
    	3RDD的数据分区特性,可以通过数据的本地性来提高性能,这与Hadoop MapReduce是一样的。
    	4RDD都是可序列化的,在内存不足时可自动降级为磁盘存储,把RDD存储于磁盘上,这时性能会有大的下降但不会差于现在的MapReduce。
    

    RDD编程接口

    	对于RDD,有两种类型的动作,一种是Transformation,一种是Action。它们本质区别是:
    	Transformation返回值还是一个RDD。它使用了链式调用的设计模式,对一个RDD进行计算后,变换成另外一个RDD,然后这个RDD又可以进行另外一次转换。这个过程是分布式的
    	Action返回值不是一个RDD。它要么是一个Scala的普通集合,要么是一个值,要么是空,最终或返回到Driver程序,或把RDD写入到文件系统中
    		
    		Transformations转换操作,返回值还是一个 RDD,如 map、 filter、 union;
    		Actions行动操作,返回结果或把RDD持久化起来,如 count、 collect、 save。
    

    RDD依赖关系

    	窄依赖(Narrow Dependencies)
    		一个父RDD分区最多被一个子RDD分区引用,表现为一个父RDD的分区;
    		对应于一个子RDD的分区或多个父RDD的分区对应于一个子RDD的分区,也就是说一个父RDD的一个分区不可能对应一个子RDD的多个分区,如map、filter、union等操作则产生窄依赖;
    	宽依赖(Wide Dependencies)
    		一个子RDD的分区依赖于父RDD的多个分区或所有分区,也就是说存在一个父RDD的一个分区对应一个子RDD的多个分区,如groupByKey等操作则产生宽依赖操作;
    

    RDD数据存储管理

    	RDD可以被抽象地理解为一个大的数组(Array),但是这个数组是分布在集群上的。逻辑上RDD的每个分区叫一个Partition。
    	在Spark的执行过程中,RDD经历一个个的Transfomation算子之后,最后通过Action算子进行触发操作。 
    	逻辑上每经历一次变换,就会将RDD转换为一个新的RDD,RDD之间通过Lineage产生依赖关系,这个关系在容错中有很重要的作用。
    	变换的输入和输出都是RDD。 RDD会被划分成很多的分区分布到集群的多个节点中。分区是个逻辑概念,变换前后的新旧分区在物理上可能是同一块内存存储
    	这是很重要的优化,以防止函数式数据不变性(immutable)导致的内存需求无限扩张。
    	有些RDD是计算的中间结果,其分区并不一定有相应的内存或磁盘数据与之对应,如果要迭代使用数据,可以调cache()函数缓存数据。
    	
    	上图中,RDD1含有5个分区(p1、 p2、 p3、 p4、 p5),分别存储在4个节点(Node1、 node2、 Node3、 Node4)中。
    	RDD2含有3个分区(p1、 p2、 p3),分布在3个节点(Node1、 Node2、 Node3)中。
    	在物理上,RDD对象实质上是一个元数据结构,存储着Block、 Node等的映射关系,以及其他的元数据信息。
    	一个RDD就是一组分区,在物理数据存储上,RDD的每个分区对应的就是一个Block,Block可以存储在内存,当内存不够时可以存储到磁盘上。
    	每个Block中存储着RDD所有数据项的一个子集,暴露给用户的可以是一个Block的迭代器(例如,用户可以通过mapPartitions获得分区迭代器进行操作),
    	也可以就是一个数据项(例如,通过map函数对每个数据项并行计算)。在后面章节具体介绍数据管理的底层实现细节。
    	如果是从HDFS等外部存储作为输入数据源,数据按照HDFS中的数据分布策略进行数据分区,HDFS中的一个Block对应Spark的一个分区。
    	同时Spark支持重分区,数据通过Spark默认的或者用户自定义的分区器决定数据块分布在哪些节点。
    	例如,支持Hash分区(按照数据项的Key值取Hash值,Hash值相同的元素放入同一个分区之内)和Range分区(将属于同一数据范围的数据放入同一分区)等分区策略。
    

    RDD有四种创建方式,如下:

        1、从Hadoop文件系统(或与Hadoop兼容的其他持久化存储系统,如Hive、Cassandra、HBase)输入(如HDFS)创建。
        2、从父RDD转换得到新的RDD。
        3、调用SparkContext()方法的parallelize,将Driver上的数据集并行化,转化为分布式的RDD。
        4、更改RDD的持久性(persistence),例如cache()函数。默认RDD计算后会在内存中清除。通过cache()函数将计算后的RDD缓存在内存中。
    

    RDD的两种操作算子

        对于RDD可以有两种计算操作算子:Transformation(变换)与Action(行动)。
        1、Transformation(变化)算子
            Transformation操作是延迟计算的,也就是说从一个RDD转换生成另一个RDD的转换操作不是马上执行,需要等到有Actions操作时才真正触发运算。
        2、Action(行动)算子
            Action算子会触发Spark提交作业(Job),并将数据输出到Spark系统。
        算子的分类:
            1、Value数据类型的Transformation算子,这种变换算子不触发提交作业,针对处理的数据项是Value型的数据。
                处理数据类型为Value型的Transformation算子可以根据RDD变换算子的输入分区与输出分区关系分为以下几种类型:
                    1、输入分区与输出分区一对一型。
                    2、输入分区与输入分区多对一型。
                    3、输入分区与输出分区多对多型。
                    4、输出分区为输入分区子集型。
                    5、一种特殊的输入与输出分区一对一的算子类型,即Cache型。Cache。
            2、Key-Value数据类型的Transformation算子,这种变换算子不触发提交作业,针对处理的数据项是Key-Value型的数据对。
                处理数据类型为Key-Value型的算子,大致分为以下几种类型:
                    1、输入分区与输出分区一对一型。
                    2、聚集(单个RDD聚集/多个RDD聚集)。
                    3、连接(对两个需要连接的RDD进行cogroup函数操作的Join/左外连接或右外连接(在Join的基础上进行))。
            3、Action算子,这类算子会触发SparkContext提交Job作业。
                本质上在Actions算子中通过SparkContext执行提交作业的runJob操作,触发了RDD DAG(有向无环图)的执行。根据Action算子的输出空间将Action算子分为以下几种类型:
                    1、无输出(对RDD中每个元素都应用f函数操作,不返回RDD和Array,而是返回Unit。即foreach。)。
                    2、HDFS(调用saveAsTextFile函数将数据输出存储到HDFS中;saveAsObjectFile将分区中的固定长度一组元素组成的一个Array然后将这个Array序列化,映射为Key-Value的元素写入HDFS为SequenceFile格式的文件)。
                    3、Scala集合和数据类型(collect;collectAsMap;reduceByKeyLocally;lookup;count;top;reduce;folt;aggregate)。
  • 相关阅读:
    cinder支持nfs快照
    浏览器输入URL到返回页面的全过程
    按需制作最小的本地yum源
    创建可执行bin安装文件
    RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
    惠普IPMI登陆不上
    Linux进程状态——top,ps中看到进程状态D,S,Z的含义
    openstack-neutron基本的网络类型以及分析
    openstack octavia的实现与分析(二)原理,架构与基本流程
    flask上下文流程图
  • 原文地址:https://www.cnblogs.com/wqbin/p/10112127.html
Copyright © 2011-2022 走看看