目录
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()
注意:
- 能不能将一个RDD使用广播变量广播出去?不能,因为RDD是不存储数据的。可以将RDD的结果广播出去。
- 广播变量只能在Driver端定义,不能在Executor端定义。
- 在Driver端可以修改广播变量的值,在Executor端无法修改广播变量的值。
- 如果executor端用到了Driver的变量,如果不使用广播变量在Executor有多少task就有多少Driver端的变量副本。
- 如果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
- FileSystem 保存元数据,需要手动切换备用Master
- 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申请资源。