Broadcast Variables广播变量
前置
一般数据存储在Driver的内存中,计算处理在Executor中,
计算过程中每个Task都要从Driver中下载一份数据,
当数据量很大时,每个Task都要从Driver中拷贝,会导致性能非常差
功能
将一个变量元素进行广播到每台Worker节点的Executor中,
让每个Task直接从本地读取数据,减少网络传输IO
特点
只读,executor端不能修改,目的是为了保证每个executor读到的内容都一致
语法
>>> broadcastVar = sc.broadcast([1, 2, 3])
<pyspark.broadcast.Broadcast object at 0x102789f10>
>>> broadcastVar.value
[1, 2, 3]
Accumulators累加器
在分布式计算场景下实现累加计算,且只能做累加
>>> accum = sc.accumulator(0)
>>> accum
Accumulator<id=0, value=0>
>>> sc.parallelize([1, 2, 3, 4]).foreach(lambda x: accum.add(x))
...
10/09/29 18:41:08 INFO SparkContext: Tasks finished in 0.317106 s
>>> accum.value
10
综合案例
# 数据源
hadoop spark # hadoop spark spark
mapreduce ! spark spark hive !
hive spark hadoop mapreduce spark %
spark hive sql sql spark hive , hive spark !
! hdfs hdfs mapreduce mapreduce spark hive
# 需求
统计数据词频时过滤非单词的符号并且统计总的个数
# 分析
#1.读取数据
把特殊字符的数据进行广播
#2.处理数据
#2.1 进行扁平化操作
#2.2 过滤操作,过滤特殊字符,并且统计特殊字符的个数
自定义函数(Driver获取广播数据,然后拿着广播数据进行匹配,如果符合,就过滤掉,然后累加,如果不符合,就放行)
#2.3 把正常的单词转换为(单词,1)
#2.4 分组聚合
#3.打印数据
# 代码实现
from pyspark import SparkContext, SparkConf
import os
import re
# 构建SparkContext
conf = SparkConf().setMaster("local[2]").setAppName("AppName")
sc = SparkContext(conf=conf)
# 1.数据输入
input_rdd = sc.textFile("/root/projects/算子/data/broadcast_data.txt")
lists = [",", ".", "!", "#", "$", "%", ""]
broadcastVar = sc.broadcast(lists)
# 1.1 定义累加器初始值0,后续只要碰到特殊符号,就累加1
acc = sc.accumulator(0)
# 2.数据处理
def filter_line(x):
listVar = broadcastVar.value
if x in listVar:
# 如果是特殊字符,应该过滤,然后统计个数
acc.add(1)
return False
else:
# 正常数据,应该放行
return True
flatmap_rdd = input_rdd.flatMap(lambda x: re.split("\\s+", x)).filter(lambda x: filter_line(x))
result_rdd = flatmap_rdd.map(lambda x: (x, 1)).reduceByKey(lambda x, y: x + y)
# 3.数据输出
result_rdd.foreach(lambda x: print(x))
# acc.value:获取累加器中的最终结果
print(f"特殊字符的个数为:{acc.value}")
# 4.关闭SparkContext
sc.stop()
# 结果输出
('spark', 11)
('mapreduce', 4)
('sql', 2)
('hadoop', 3)
('hive', 6)
('hdfs', 2)
特殊字符的个数为:14
Process finished with exit code 0
小结:
累加器一般用于黑名单、特殊词等统计中。
广播变量是把小的数据集广播到各个Executor节点上,接上网络数据传输。
Spark的内核调度
(1)先启动分布式资源管理的集群:Spark Standalone / YARN
(2)客户端提交用户开发好的Spark Application程序给ClusterManager
(3)ClusterManager根据配置参数运行程序,启动Driver进程
(4)Driver进程向主节点提交申请启动Executor进程
(5)主节点根据资源配置和请求,在从节点上启动Executor进程
(6)所有Executor启动成功以后,会向Driver反向注册,等待分配Task
(7)Driver解析代码,直到遇到触发算子,开始触发job的运行
(8)Driver会调用DAGScheduler组件为当前这个job构建DAG图,并划分Stage
(9)Driver会将这个job中每个Stage转换为TaskSet,根据Stage中最后一个RDD分区数来构建Task个数
(10)Driver调用TaskManager将每个Stage中的Task调度分配到Executor中运行
(11)任务执行完后,Executors和Driver都被销毁,资源被释放
Spark的Shuffle机制
因为具有某种共同特征的一类数据需要最终汇聚到一个计算节点上进行计算。
这些数据分布在各个存储节点上,并且由不用的计算单元进行处理。
这种数据打乱然后汇聚到不同节点的过程就是Shuffle。
简单理解,当需要对所有数据进行**全局**分组、聚合、排序时,就需要经过shuffle
Spark Shuffle过程也叫作宽依赖过程
会经过shuffle过程的有:
#1.重新分区
repartition
#2.全局排序
reduceByKey、groupByKey
#3.全局分组
#4.join操作
join
Sort Shuffle中,有两种Shuffle机制,一种是普通机制,一种是ByPass机制