pyspark使用心得
- 分布式处理大规模数据,底层还是spark,包了一层python api
- 一般公司的基建是优先支持hive的,当hive写不出sql处理大数据时,考虑用pyspark
- pyspark对调试不太友好,写之前对数据要有充分认识,不然调试一次时间成本较大
- 作为数据挖掘工程师,了解底层原理,熟练语法即可,重点是对数据的认识与应用
pyspark运行架构
spark运行架构
- spark基于分布式运行,简单理解就是主从结构,Master负责分发任务,Worker负责执行任务,再搭配 Yarn,Mesos等做资源管理。
pyspark 运行架构
- pyspark主要是在Master节点(Driver),利用Py4j实现python和java交互来实现python编写spark应用程序。因此天然的pyspark会比scala原生写的spark运行慢。
更简单的示意图:
- Driver端,spark执行需要在jvm中,python通过py4j将python程序转为jvm执行程序。这里的问题是py4j通信方式是:序列化-传输-反序列化。如果python进程和jvm有大规模数据交互,效率比较差。因此后面出现的apache arrow来解决这个问题
- Executor接收任务Driver端转好的jvm程序,一般在本地的jvm就可以执行基本任务。只是pyspark一般会有很多自己写的udf或者其它python相关包(numpy,scipy等),需要调用本地python进程执行任务。
spark基础概念
RDD
- 弹性分布式数据集(Resilient Distributed Dataset),理解成一个数据格式,记录数据在各个分区,以及相关血缘关系。spark处理数据的基本格式。
- RDD的操作有两种类型,Transformation操作和Action操作(或者叫算子)
- Transformation:转换操作,从已经存在的RDD创建一个新的RDD,当前从节点运行
- Action:行为操作,RDD上进行计算后返回结果到 Driver,涉及集群通信
- Transformation是lazy特性,不会立即执行,只有触发Action操作才会真正执行
- 这里的操作就是不同计算函数,比如 groupBYkey、reduceBykey、aggergateBykey、join、cogroup、repartition
DAG
- Directed Acyclic Graph(有向无环图)
- 反映RDD之间的依赖关系, RDD由不同算子组成的依赖关系即为一个DAG,
- DAG会根据依赖关系的不同划分成不同的Stage
- 窄依赖:父RDD的分区和子RDD的分区的关系是一对一或者多对一的关系
- 宽依赖:父RDD的分区和子RDD的分区是一对多或者多对多的关系
- 多个窄依赖合并成一个stage,宽依赖单独是一个stage
- stage1 和 stage2都是由窄依赖构成
- stage3是最外围的虚线框,执行最后的groupby和join操作
数据倾斜
- 在spark中出现的数据倾斜,主要是数据分配不合理,大量相同的key被分配到同一个任务,使集群只有少部分节点在跑任务,其余节点空闲。 计算效率低同时浪费资源
- 常见在 groupBYkey、reduceBykey、aggergateBykey 等需要进行数据shuffle的算子中。即需要对数据进行分配。
- 如何发现:去spark ui上看执行节点分配是否合理。一般url都是集群ip:4040
总结
- pyspark是在spark基础上包装了一层python api,底层执行还是依赖spark架构。
- spark执行主要是根据代码写的一套计算流程形成DAG,划分成不同Stage,每个Stage看作一个Task(Driver端完成),然后分发给不同Executor执行。(Driver和Executor通信是就是通的这些东西以及计算完后的结果)
- 注意解决数据倾斜,常见2种方法
- 加资源
- 数据加盐