spark学习(四):共享变量及一些优化

目录

1.Spark中的共享变量

1.1 广播变量

1.2 累计器

2. Spark WEBUI

3. 搭建HistoryServer

4.Master HA


1.Spark中的共享变量

在spark程序中,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的是这个函数所用变量的一个独立副本。这些变量会被复制到每台机器上,并且这些变量在远程机器上的所有更新都不会传递回驱动程序。通常跨任务的读写变量是低效的,但是,Spark还是为两种常见的使用模式提供了两种有限的共享变量:广播变(broadcast variable)和累加器(accumulator)

1.1 广播变量

为什么使用广播变量
        当在Executor端用到了Driver变量,不使用广播变量,在每个Executor中有多少个task就有多少个Driver端变量副本,当task数很多时,Driver端的带宽就会成为系统的瓶颈,并且会消耗大量task服务器的资源。
        如果使用广播变量在每个Executor端中只有一份Driver端的变量副本。

广播变量图解

不使用广播变量

使用广播变量

使用广播变量

定义一个广播变量

val  a = 3

val broadcast = sc.broadCast(3)

获取变量的值

            val value = broadcast.value()
     
注意:

  1. 能不能将一个RDD使用广播变量广播出去?不能,因为RDD是不存储数据的。可以将RDD的结果广播出去。
  2. 广播变量只能在Driver端定义,不能在Executor端定义。
  3. 在Driver端可以修改广播变量的值,在Executor端无法修改广播变量的值。
  4. 如果executor端用到了Driver的变量,如果不使用广播变量在Executor有多少task就有多少Driver端的变量副本。
  5. 如果Executor端用到了Driver的变量,如果使用广播变量在每个Executor中只有一份Driver端的变量副本。

规则库,中间库,知识库数据等,稳定,会被数据分析被频繁的使用到。数据量不会太大。 这些数据,就优先考虑把这些数据进行广播。

1.2 累计器

为什么要使用累加器?

在spark应用程序中,我们经常会有这样的需求,如异常监控,调试,记录符合某特性的数据的数目,这种需求都需要用到计数器,如果一个变量不被声明为一个累加器,那么它将在被改变时不会再driver端进行全局汇总,即在分布式运行时每个task运行的只是原始变量的一个副本,并不能改变原始变量的值,但是当这个变量被声明为累加器后,该变量就会有分布式计数的功能。

例如

// 计数器
var counts = 0 // Driver端定义的

val rdd1 = sc.makeRDD(List(1, 3, 4, 5, 6, 7, 9), 2)

// 统计 数据的条数  executor端执行的
rdd1.foreach(t => {
  counts += 1
  println(s"---+${counts}")
})

// 期望:7  实际:0  // Driver端的数据没有变
println(counts)

累加器图解

不是用累加器,

使用累加器


使用累加器

定义一个累加器

val accumulator = sc.accumulator(0)

获取累加器的值

val value = accumulator.value    

自定义累计器 ,实现AccumulatorParam<xxx>  实现三个方法zero,addAccumulator,addInPlace
        val accumulator = sc.accumulator(xxx,new AccumulatorParam...)
        accumulator.add(xxxx)

注意事项
            累计器只能在Driver定义初始化,在Executor端更新,在Executor不能accumulator.value获取值。
            

2. Spark WEBUI

 

 4040端口可以看到当前application中的所有的job,点击job可以看到当前job下对应的stage,点击stage出现stage下的task。

 

 

3. 搭建历史服务器HistoryServer

1).在客户端中../conf/spark-defaults.conf文件中配置:

  • 开启记录事件日志的功能

spark.eventLog.enabled                   true

  • 设置事件日志存储的目录

spark.eventLog.dir                           hdfs://hadoop101:9000/spark/log

  • 设置HistoryServer加载事件日志的位置(恢复时加载历史文件的路径,就是你存储事件日志的路径)

spark.history.fs.logDirectory            hdfs://node1:9000/spark/log

  • 日志优化选项,压缩日志(记录的历史事件日志没有压缩)

spark.eventLog.compress               true

2).启动HistoryServer:

 在../conf/sbin/start-history-server.sh

3).访问:node4:18080      

 

搭建了历史服务器HistoryServer后,就算是application推出之后,也可以查看历史事件日志记录

 

4.Master HA


Master是JVM进程有可能挂掉,当Master挂掉之后,不能提交Driver,我们需要搭建Master HA

  1. FileSystem  保存元数据,需要手动切换备用Master
  2. Zookeeper  分布式协调服务,保存元数据,自动切换
  • 在集群的每台节点../conf/spark-env.sh 中配置:

export SPARK_DAEMON_JAVA_OPTS="

-Dspark.deploy.recoveryMode=ZOOKEEPER

-Dspark.deploy.zookeeper.url=hadoop101:2181,hadoop102:2181,hadoop103:2181

-Dspark.deploy.zookeeper.dir=/MasterHA"

  • 在StandBy-Master(hadoop102)节点中修改../conf/spark-env.sh:SPARK_MASTER_IP = hadoop102
  • 启动Zookeeper
  • 在Alive-Master节点上启动集群:../sbin/start-all.sh
  • 在StandBy-Master节点上启动StandBy-Master ../sbin/start-master.sh
  • 测试。

        注意:
            a).这里的Master HA是针对的standAlone集群
            b).主备切换过程中,不影响已经在集群中运行的程序
            c).主备切换过程中,影响向Master申请资源。

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