[大数据]连载No8之Spark(集群客户端+控制类算子+广播变量+任务调度)

本次总结图如下


修改集群webUI端口两种方式
方式一:conf/spark-env.sh  添加SPARK_MASTER_WEBUI_PORT

方式二: sbin/start-master.sh 修改8080

搭建spark集群客户端
必要性:spark集群客户端提交应用时,承担磁盘IO,并且独立于spark集群,,不会影响spark集群某个节点性能差异
注意:客户端节点不用在slaves配置,也不会启动任何进程,但是要和master互相同行
配置:非常简单,只需要将配置好的spark安装包拷贝到客户端节点,不需要任何配置


spark-submit背后执行流程
1:spark-submit提交后,客户段开启一个Driver(JVM)进程,并且会将jar和相关依赖的jar上传到spark FTP服务器上,然后向Master申请资源,
2:msster找到资源充足的worker节点,在worker节点启动executor(jvm集成)进程,这个进程中有一个Threadpool,在这个线程池中,能执行task(Thread线程)
3:executor启动完成后反向注册给Driver。Driver就会拥有一批Executor列表,也就可以分发task到Executor中执行,如果有依赖jar,就会从ftp下载

图 spark-302Spark执行流程.png

spark-shell
使用方式:[root@master spark-1.6.0]#  ./bin/spark-shell --master spark://master:7077
原理:底层封装submit,spark-shell,相当于提交一个应用程序到spark,并且自己会创建Sparkcontext对象 sc

注意:如果执行foreach算子,会将函数推送到Executor段执行,,并不会将结果拉回到Dirver,如果要在命令行看到结果,需要使用collect算子,collect是用于测试用,一般生产不会用此算子

控制类算子的RDD的持久化
cache
 1:cache算子是一个懒执行算子,需要action算子才能执行 2:对某一个算子执行cache,需要将结果赋值给一个变量,在接下来的job中可以直接使用这个变量,那么就可以读到缓存的数据
 3:如果要释放缓存数据,使用unpersist方法,  使用unpersist方法是立即执行算子
 4: cache类算子不可以立即紧跟action算子,例如 rdd.cache().count, 它返回的不是rdd,后面再使用rdd算子,不能从内存读取了
presist
1:原则:在spark中持久化单位是partition
1:常用持久化级别
  >MEMORY_ONLY (将RDD的数据写在内存里),等价于cache()
  >MEMORY_AND_DISK (将rdd的数据写在内存里,如果内存写不下,就写在磁盘中,注意,spark单位是partition,如果内存写不下,就全部写在磁盘,不会一半数据在内存,一半在磁盘)

  >MEMORY_AND_DISK_SER(数据序列化再持久化)

广播变量和累加器  
伪代码一,记录数累加

var rdd1=sc.textFile("log")
var count=0
rddLine.map( x=>{
  count +=1
}).count()
println(count)
  注意:打印count结果为0
  解释:Driver端开启一个Dirver进程,此时count变量存在Dirver进程中,然后分发task到Exetutor节点执行,Exetutor发现用到count变量,那么会把count变量保存一个副本,再发送到一个个Exetutor里去执行,此时已经不是Dirver集成的变量了,Task里面逻辑就是匿名函数里的逻辑
解决办法
spark累加器:集群中的一个大变量
1:只能在Driver端定义和读取
2:累加器不能再Exetutor读取,但是可以操作累加的,累加时(accumulator.add())其实还是调用Dirver端执行的

优化代码
var accumulator = sc.accumulator()
rddLine.map(x => {
  accumulator.add()
}).count()

println(accumulator.value)

伪代码二,过滤黑名单
val rdd1=sc.textFile("log")
val blackList=List("java","C++")

rdd1.filter( x=>{
  !blackList.contains(x)
}).collect()
  注意:不是最优的代码,如果blackList是一个非常大的集合,那么每个Executor都有这样一个副本,集群占用内存是非常大的
解决办法
广播变量:集群中的一个大常量
1:实在Driver端定义和修改
2:Exetutor只能读取,不能修改
优化代码
val rdd1=sc.textFile("log")
val blackList=List("java","C++")
val blackNameListBoast=sc.broadcast(blackList)
rdd1.filter( x =>{
  ! blackNameListBoast.value.contains(x)
}).collect()

任务调度
1:RDD的依赖关系
宽依赖:父RDD于子RDD是一对多的关系,一般来说,宽依赖是于shuffle对应
窄依赖:父RDD于子RDD是一对一或者多对一的关系


2:概念解释
Mster:资源管理的主节点(只是一个进程)
Cluster Manager:集群管理者
Worker:资源管理的从节点(或者说本机资源管理者)
Application: 基于Spark的用户程序
Job:包含很多任务(Task)的并行计算,可以说几个Action算子,就是几个job
Stage:一个job会被拆分很多组任务,每组任务被称为Stage
Task:被送到某个Executor执行的工作单元

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

源14

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值