spark学习

总是学了就忘记,spark都学了几遍了  总是深入不进去  唉  头疼  这里再次学习一遍  谁有更好的深入学习spark的方法给推荐推荐

面试了大数据,盘点几个被问到的问题: 

    spark一定会把中间结果放在内存吗?当然不是  可以是内存,也可以是磁盘  

    spark包括work和master   work和master之间的沟通通过网络RPC进行交流沟通

拷贝到其他节点 for i in {5..7}; do scp -r /bigdata/spark/conf/spark-env.sh node-$i:$PWD; done

    spark是移动计算,而不移动数据   因为大量数据移动成本大 

   spark是Scala 编写  spark包本身有Scala编译器和库  但spark是运行在jvm上的  需要安装jdk

  

利用zookeeper实现高可用集群   zookeeper用来1选举 2保存活跃的master信息 3 保存worker的资源信息和资源使用情况(为了故障切换转移)  在env.sh中添加export SPARK_DAEMON_JAVA_OPTS="-Dspark .deploy.recoveryMode=ZOOKEEPER xxxzookeeper相关信息"   高可用的spark需要手动启动另一个(standby)spark-master  并不会随着spark-all.sh 启动master

 

一直搞不懂spark进程之间的关系   下面来理一下:

提交任务的机器(Driver)(spark-submit提交jar包的那个) 有SparkSubmit进程,有CoarseGrainedExecutorBackend(这个是executor,即worker的哦哦用来执行任务的进程),Worker进程(worker机器所在)     任务执行完成后  Executor进程会释放    jps不在拥有Executor进程

 

在没有集群的时候  master会负责资源调度  保存worker资源情况  根据客户端submit要求分配资源,即master和worker进行rpc通信,然后worker进程启动executor(CoarseGrainedExecutorBackend),将分区参数传递过去

真正的计算逻辑是在driver端(submit端),生成task,然后通过网络发送给各个executor进行执行。executor启动后会主动连接driver,然后driver才开始生成task。两者之间的通信当然是通过master到worker进而知道的executor在哪里

 

yarn和spark的stondalone对比

resourcemanager     对应  Master  都用来管理子节点和资源调度,接收任务请求

nodeManager         对应    Worker  管理当前节点,并管理子进程

yarnchild                对应      executor  用来运行真正的计算逻辑

applicationMaster用来管理yarnchild,,决定map reduce运行在哪一个yarnchild

yarn还有client用来提交任务         这两个综合起来相当于spark的SparkSubmit (提交app,管理度任务的executor并将task提交到executor)

RDD是弹性分布式数据集,rdd并不存储真正的数据,只是一个抽象,对rdd操作,会在driver端转换成task,下发到executor计算分在多台集群上的数据

rdd是一个代理,对代理进行操作,会生成task帮助你计算,操作这个代理就像操作本地集合一样方便

RDD有分区,是通过内部进行指定    分区里面记录的是位置变量(以后要读取哪部分数据),生成的task交给executor,每个分区交给一个task去执行 ,然后task读取数据去执行相应的操作   

aggregate方法,aggregate(0)(_+_ , _+_)   聚合操作,执行操作,每个分区分别执行,返回的顺序不一定有序

aggregateByKey(0)(_+_ , _+_) 每个分区局部相加  再全部相加   假如说原RDD(pairRdd)有两个分区,经过转换后变成shuffledEdd(也有两个分区,但分区内容是shuffle后的)

reduceByKey(_+_)

countByKey()

task在executor运算完成后,收集最终的数据到driver端   现在如果收集数据到redis  mysql 或者hbase,那么不应该先collect收集数据到driver端,因为数据量过大,容易使得driver端崩溃  

Rdd 的map方法,真正的在executor中执行的时候,是一条一条的将数据拿出来处理

foldByKey()

filter()

action:

rdd.collectAsMap()    

foreach(e =>println(e*100))  一条一条的拿(一条一条的执行function)

foreachPartition()   每个分区拿(一个分区执行一个function)

combineByKey(x=>x,(m:int,n:int)=>m+n, (a:Int,b:Int)=>a+b)   (m+n 是分区聚合  a+b 是全局聚合,key 保持不变,对value操作,最后生成shuffledRdd)

 

Spark执行流程:

这个图虽然是到处都有   但真的很重要  理解他  记住他  spark基础就完全ok了

1构建DAG(所谓的DAG就是描述的一个个RDD的转换过程)(开始通过SparkContext创建RDD,结束调用runJob(也就是触发action)就是一个完整的DAG过程了)(有多少个DAG,取决于触发了多少次action)

2将DAG切分成stage(DAGSheduler)(切分的依据是shuffle),将stage中生成的Task以taskset的形式给TaskSheduler    将多台机器上具有相同属性的数据聚合到一台机器上:shuffle    如果有shuffle,那么就意味着前面阶段产生结果后,才能执行下一个阶段,下一个阶段要依赖上一个阶段的数据,在同一个stage中,会有多个算子,我们称其为pipeline

shuffle的含义:父RDD的一个分区中的数据如果给了子RDD中的多个分区(只要存在这种可能,例如款依赖时候如groupbyKey,他也有可能前一个步骤分区全部到下一个步骤的一个分区,但他可能分配到分多个分区,那么也是shuffle),就是shuffle

宽依赖(shuffle)   窄依赖      

rdd1=sc.parallelize(List(("tom",1),("ketty",2),("tom",2)))  这个过程是把一个list shuffle到

不同分区的过程,所以也被分成一个stage

当然并不是所有的join都是宽依赖   如果前面的rdd数据比较规整  不需要shuffle到不同的分区 那么就是窄依

然后执行完第一个阶段后会执行第二个阶段的task,同样是driver端生产task  然后序列化,网络传输到executor端进行反序列化,然后封装成Runnable实现放到线程池进行处理

 

对RDD操作实际上是对分区进行操作 ,分区再生成task到executor执行操作

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章