Spark VS Mapreduce
Spark
- 基于内存的计算
- 高性能要求
应用场景
- 高迭达类型的计算
增加了Driver新组件
- Client收到应用请求,首先会拉起Driver,主要是用于Spark的工作流程规划和TASK下发。
RDD算子
- 执行类的算子
- 逻辑操作类的算子
整体流程
- 用户向Client提交应用,Client接收
- Client向RM提交请求,申请应用,RM中的APPMANAGER会返回一个JOB-ID
- CLIENT下发应用,通过对应用到进行解析,我们可以提取并且加载DRIVER,DRIVER一般是运行在CONTAINER中的,和MR中的APPMASTER一样,当然用户亦可指定DRIVER的执行位置
DRIVER启动之后,会联系APPMANAGER,下发APPMASTER程序,APPMANAGER收到请求之后,会向ResourceManager查询当前集群中节点的负载情况,选择其中负载最小值的VM,然后要求其拉起Container,并且将APPMASTER下发到其中运行。
- APPMASTER启动之后,无需注册,直接计划当前的应用需要消耗的资源,DRIVER会根据应用的执行情况,将应用切分为Aplication(个数为1)
DataSet
- 以行为单位的数据
DataSet 特点
- 快,大多数场景下性能优于RDD,Encoders优于Kryo或者Java序列化;避免不必要的格式转化。
- 类型安全:类似于RDD.
DataFrame
- 以列为单位的数据
SparkStreaming with SparkStructuredSreaming with Storm的关于
SparkStructuredSreaming仅供SparkSQL上层使用,它可以将原行细碎化的SQL操作转换为流式操作,使数据安全
HBase
HBase是一个分布式的数据库,其义底层的数据文件是以HDFS文件维护在DataNode上。HBase自身其实不带数据存储功能的。所以必须要依托于HDFS。
- HBase是一个非关系型数据库,所谓非关系型,是指它既可以存储结构化数据和半结构化数据。
- HBase是一个面向于列的数据库,一般的数据库,我们在写入数据之前首先需要设计表的结构,表的结构指的就是列属性。
HBase与RDB对比
HBase读流程
- 用户发送请求到达Client.
- Client向Zookeeper发送元数据请求。ZOOKEEPER收到之后直接反馈。 1.CLIENT根据元数据中存储的REGION路由信息,找到维护相关的数据REGION
HBase写流程
- 用户发送请求到达Client.
- Client向Zookeeper联系,如果是新写,那么大就要求ZOOKEEPER创建元数据分配写空间,如果是改写,那么就读元数据。
ZOOKEEPER反馈之后,下一步用户名会联系REGIONSERVER,如果写新数据之时,未创建新的Region, 则CONTACT元数据所记录的RegionServer, 假如新写入数据量过大,则Hmaster就需要创建新的Region,并且指派某个RegionServer进行管理,那么大Client就需要联系这个新的RegionServer.
CLIENT将数据下发给RegionServer,由RegionServer联系对应的Region写入数据, 先将数据写入内存中,之后在写日志。
今天开始不小心把轮子碰到马路牙子上去,刮伤了提车刚好满一个月
MapReduce:离线计算引擎 Spark:基于内存的计算引擎 Storm:实时流计算引擎 Spark的特点: 轻:轻量级,核心代码较少,但是表达的功能很全面 快:基于内存的计算可以使Spark的计算时间压缩到亚秒级 灵:Spark具有超乎于其他组件的灵活性,它可以独立部署,也可以加入到hadoop平台中 进行统一的部署,而且它可以支持yarn,也可以独立进行资源管理等相关的操作。 巧:巧妙借力于现有的大数据组件。Spark可以和现有的hadoop中的相关的组件进行相互之间的功能调用和相关的维护操作等 Spark和MR的关系 MR是离线计算引擎,它的所有的中间结果,除了存储到环形内存缓冲区以外,其他的所有数据都必须存储到硬盘上。所以它在进行临时文件的管理操作的时候,就会比较慢,因为数据要先存储到磁盘上,然后在被读取,整体的性能就会收到影响。 Spark将所有的数据包括中间计算的临时数据都存储到了内存中,那么这样做的话在反复调用的过程中,Spark就无需先将数据存储到硬盘中之后再进行 读取了。这样的话MR和Spark的区别就很明显了,MR由于其将数据存储到硬盘中,所以MR对于高迭代计算和频繁的引用数据,就会产生读取的高延迟,那么进行迭代计算就是MR的软肋,而这一部分操作 对于Spark来说,压力就没有这么大,因为它将所有的数据都存储到内存中,就便于进行迭代 计算。 但是同时在进行 大量数据的流式操作的计算时,由于Spark将数据存放 在内存中,所以大量数据就会占用很多的内存,所以对于海量的数据计算,数据还是存放在硬盘中要比存放在内存中要好的多, 综上,对于高迭代频繁引用的计算来说,更适合 使用Spark,对于海量数据计算来说,更适合使用MR。 Spark组件: standalone和mesos是Spark单独部署的时候使用的相关组件 Yarn,当Spark部署在Hadoop上的时候,我们使用的就是Yarn来进行集群的资源管理。这样做也便于结果和资源的共享。 SparkCore:SparkCore是Spark组件的核心计算引擎,它负责了Spark中所有组件的计算工作。 那么在Spark的上层,根据使用的场景不同,我们分成了很多 相关的组件 来进行不同应用的计算。 SparkSQL,SparkSQL主要负责的就是对SQL指令进行解析和计算操作。那么SparkSQL主要负责的就是对用户 提交的SQL指令进行解析,并且将计算工作提交给Core进行计算、 structuredstreaming:快速的流计算引擎,该组件是Spark2x中新加入的组件,它可以提供比传统的SparkCore更优秀的计算性能和安全性。所以目前Spark2x版本中,我们更多的使用的是该组件的计算解析功能。 SparkStreaming:是早期的流式计算引擎,但是目前由于structuredstreaming的出现,所以使用的情况越来越少。 其余 的三个组件主要是负责提供算法库,java连接的解析库等相关的数据存储。相当于其就是Spark的字典。 Spark应用执行流程 1.用户向Client提交请求,下发应用程序。 2.Client收到应用程序之后,首先会选择拉起Driver,Driver是Spark中的一个新的组件,主要是用于进行Spark的工作流程规划和task下发。 3.Driver在收到用户请求之后,首先会下发请求到RM中的APPManager,要求拉起AppMaster。并且同时Driver会计算应用执行的DAG(有向无环图-执行规划) 4.APPManager收到请求之后 ,下一步会向RS查询当前集群中负载最小的NM,然后选择在压力最小的NM上拉起一个Container,然后将AppMaster下发到其中运行。 5.AppMaster拉起之后,无需注册,直接计算当前应用需要的所有资源并且进行相关的申请操作。至此,AppMaster所有的工作都已经结束。 6.RM中的RS收到请求之后,就会按照task为单位分配NM的资源,要求NM在自身本地拉起并且创建Container,然后在Container中创建executor。 7.executor创建完成之后,(由于executor是容器的进一步细分的资源集成体,它的工作就是获取task并且执行对应的操作,所以executor下一步就要联系任务的分发者,driver),首先会向driver进行注册,之后driver会下发task给executor进行相关的计算。 8.当executor计算完成之后,会向Driver注销自己 ,并且释放资源,AppMaster的资源会被APPManager直接回收,Driver在完成任务之后,直接关闭掉 自己。整体任务结束。 RDD:RDD叫做 动态分布式数据集,我们将完整的 数据切分成为一个个的只读的分区数据,那么这些数据就叫RDD。通过对RDD的切分,我们可以将原本的多层迭代划分开,把原本的计算中的依赖关系和迭代,转化成了 RDD的也就是数据层面的迭代和依赖关系,让逻辑计算和实际的数据相互吻合。RDD是具有血统机制的。存在有父RDD和子RDD。通过父RDD 我们可以得到子RDD。这种情况下,一般我们需要得出的最终结果往往是最小的子RDD,而第一步计算的数据源往往是最大的父RDD、 除了父子关系之外,RDD还存在有宽窄依赖。所谓宽依赖指的就是子RDD中的分区依赖于父RDD中的所有分区,而窄依赖指的是父RDD中的分区最多被一个子RDD的分区所用。当Spark在规划DAG的时候,凡是遇到宽依赖,必须要拆分成窄依赖、由于在实际的操作环境中 ,一旦宽依赖中的某一个值被卡住,无法计算,那么其他的值在正常计算的情况 下,还会按照执行流程进一步的去做执行和装载操作,虽然计算正常的值可以进行正常的操作,但是对于卡住的值,由于其计算失败,就会导致其他相关联的计算都出现问题,所以就算正常的值被装载也无法计算,这样的话,不仅卡住的计算数目会增加,而且正常装载的值,也会占用更多的内存。所以我们要将宽依赖拆成窄依赖。 RDD算子 在实际的计算操作中,实际上我们有两种类型的算子,一种是逻辑操作的算子,另一种是执行类的算子,如果我们把每个逻辑算子都执行计算,那么对于内存的占用量就会比较大,所以这个时候,我们提出了一种方案,就是对逻辑计算的算子先不做计算,而等到必须要对逻辑算子做计算的时候再去进行计算,那么我们就分为了如下两种算子 transformation算子:该算子也就是指逻辑计算算子。 action算子:实际的操作算子,当一个执行流程遇到action算子的时候,就会将之前所有的transformation算子一起执行操作。 总体来说。关于 RDD算子的计算主要根据以下 方式,当遇到transformation算子的时候,先行略过,不进行计算,而遇到action算子的时候,就要将该action算子和之前略过的transformation算子一起执行相关的计算。这样做的好处就是减小了临时迭代数据对内存的长时间占用。因为一旦迭代数据长时间的占用内存就容易导致内存的不足,这样如果有突发的大量计算,就会影响整体的计算性能。 DAG(运行规划-有向无环图) 一个任务的执行是一定有始有终的,不会出现无限的循环执行,所以当一个任务提交到Spark中的时候,我们就需要为该任务创建一个DAG也就是运行的规划,创建一个好的运行规划可以在最大的程度上,节约内存的使用量,并且可以提升计算的效率,所以DAG是一定要进行相关的规划的,而规划DAG是driver的工作。 DAG将一个应用切分成为了application、job、stage、task四个层次、 首先,一个应用提交上来就是一个application,所以application的个数恒定为1 job就是指action算子的个数。每当遇到一个action算子就切分一次job stage就是指宽依赖的个数、每当遇到一个宽依赖算子就切分一次stage task就是实际的执行命令。 Spark整体流程(详细) 1.用户向Client提交应用,Client接收 2.Client向RM提交请求,申请应用,RM中的APPManager会返回一个jobID 3.Client下发应用,通过对应用进行解析,我们可以提取并且加载Driver,Driver一般是运行在Container中的,和MR中的AppMaster一样,当然用户也可以指定Driver的执行位置。 4.Driver启动之后,下一步就会联系APPManager,下发AppMaster程序,APPManager收到请求之后,会向RS查询当前集群中的节点的负载情况,选择其中负载最小的NM,然后要求其拉起Container,并且将AppMaster下发到其中运行。 5.AppMaster启动之后,无需注册,直接计算当前的应用需要消耗的资源,Driver会根据应用的执行情况,将应用切分为Application(个数为1),Job(每当遇到action算子则切分),stage(遇到RDD的宽依赖的时候拆依赖形成),task(每一个或者多个执行指令为一个task)。形成DAG,AppMaster会根据Driver拆分的task,依次向RM中RS去申请executor。 6.RS收到AppMaster的请求之后,会根据集群负载要求集群中的NM拉起Container,并且在Container中运行Executor。 7.Executor启动之后,首先会和Driver进行注册,注册完成之后Driver会下发对应的task到Executor中执行。 8.Executor执行完成后,会返回结果 ,并且向Driver注销自己,之后释放资源,由NM回收,并且周期上报资源情况给RS。 9.Driver在整理了所有的计算结果之后,会生成一个结果给Client,并且反馈给用户,之后AppMaster自我注销,Driver自我注销。 10.如果在执行流程中,用户需要进行查询操作,那么client会将用户的请求转发给Driver进行查询。因为Driver掌握整体应用的任务执行下发,和执行情况查询功能。 Dataset:一组由特定域的对象组成的强类型集合,它和RDD最大的不同是RDD中,只有数据,数据以分区的形式存在。 Dataset除了数据以外还包含了部分的属性和结构信息。比如作为一个表,那么我们可以抽出若干行数据作为一个Dataset,该Dataset中包含了数据,结构,属性等相关的信息。 和RDD不同的是,RDD存储时,存储的是实际的数据编码信息,比如用ASCII码进行编码,但是Dataset使用的是二进制编码,一般来说,在Spark中,为了节约 内存我们一般使用的都是二进制编码,那么数据如果说在SparkCore中,使用RDD计算,就必须将二进制编码转换为SparkCore可以识别的数据,我们将这个数据转换过程叫做反序列化。DataSet默认存储就是使用二进制编码,而且它的二进制编码可以被Spark识别,这样的话,我们就无需进行反序列化操作 就可以直接进行计算。提升了整体系统的处理性能。 序列化:将多种编码格式的数据转换为二进制编码 反序列化:将二进制编码的数据转换为Spark可以识别的数据 那么Dataset和RDD一样,都是属于lazy的,他们只有遇到action算子的时候才会去执行实际的操作。 DataSet和Dataframe 在一个SQL表格中,Dataset表示的是以行为单位的数据,DataFrame是以列为单位的数据。 那么如果采用行存储,那么每一行就是一个基本的单位。那么如果我们想要读取出其中的某一列数据,就必须下发多次读请求。 那么如果采用列存储,那么每一列就是一个基本的单位。那么如果我们想要读取出其中的某一行数据,就必须下发多次读请求。 而在 SparkSQL组件中,我们使用的是列性质的维护方式。由于Spark一般多用于数据分析和数据挖掘中,作为数据分析师更多的是会去关注某个属性对其他属性或者是结果的 相关影响,所以这个时候,关注点更多的是在属性上,为了减小读请求的次数,那么我们更多的是采用列存储,也就是以一列作为一个基本的维护单位。这样的话,如果我们需要读取一列,只需要下发一次读请求即可。 structruedstreaming 流式计算工具、增量计算工具、建立在SparkSQL的基础上。 一般来说,我们在执行计算的时候,首先定义好数据源,定义好方法,然后输入进行执行。这种情况下,我们就把数据源叫做静态RDD。但是作为流式数据计算引擎的特点就是数据源不固定。所以本身流式数据计算引擎在进行计算的时候本身就很难对数据去做相关的定义式操作,那么structruedstreaming一个最大的特点就是其可以将流式数据按照静态RDD数据的形式来进行编译和使用,这样做就可以在最大的程度上提升数据的安全性和计算的性能。 该引擎在执行具体的操作的时候,不是数据上传上来就马上执行,而是根据时间间隔(默认1s,用户可自定义),每当到达时间间隔的时候,其就会对数据(新增加的数据,或者是从开始执行到当前时间新增加的数据) SparkStreaming和SparkStructuredStreaming和Storm的关系 SparkStructuredStreaming仅供SparkSQL上层使用,它可以将原先细碎化的SQL操作转换为流式操作,使数据安全性和处理效率增加。 SparkStreaming对文件格式无要求,它是建立在Core上的流式计算引擎。 SparkStructuredStreaming和Storm没关系 SparkStreaming和Storm的关系
