一、简介
Spark:是一个并行分布式计算引擎
二、说明
相比于MapReduce
- 数据处理过程
- MapReduce:把数据从磁盘读到内存,在内存中完成计算,再写回磁盘。下一个mr程序要继续对这批数据进行处理,又要重复这一过程。有多少个mr程序,就有多少次读磁盘和写磁盘的过程,效率低下。
- Spark:把数据读到内存之后,在多个RDD之间形成转换流,而RDD借助于exector的缓存,是可以在内存中完成计算。因此只需要一次读和一次写磁盘的过程。
任务处理流程
- 1、client提交应用
- 2、master找到一个worker启动driver
- 3、driver向master或者资源管理器申请资源
- 4、之后将应用转化为RDD Graph
- 5、再由DAGScheduler将RDD Graph转化为stage的有向无环图提交给taskscheduler
- 6、由taskscheduler提交任务到executor执行
任务计算过程
- 1、driver向rm提交作业
- 2、rm创建一个am
- 3、am向rm申请资源
- 4、rm返回可用的资源列表
- 5、am据此创建executor对象
- 6、executor向am进行反向注册,告知哪些executor注册成功,可以执行任务,为后续的am调度任务提供依据
- 7、am分解任务,并调度任务。
- 8、executor执行任务并返回结果
- 9、driver执行结束,am撤销
任务进程
-
Driver:执行开发程序中的main方法的进程。负责创建SparkContext、创建RDD、进行RDD的行动操作代码的执行
- 1、把用户程序转为JOB
- 2、跟踪Executor的运行状况
- 3、为Executor调度任务
- 4、UI展示应用运行状况
-
Executor:工作进程。负责运行任务,任务间相互独立。Spark应用启动时,Executor节点被同时启动,并且始终伴随着整个Spark应用的生命周期
- 1、负责运行组成 Spark 应用的任务,并将结果返回给Driver
- 2、通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD提供内存式存储。RDD是直接缓存在Executor进程内的,因此任务可以在运行时充分利用缓存数据加速运算。
代码优化
- 避免重复创建rdd
- 复用rdd
- 多次使用的rdd持久化
- 避免使用shuffle类算子
- 使用map-side预聚合
- 使用高性能算子
- 广播大变量
- 使用Kryo优化序列化性能
- 优化数据结构
- Data Locality本地化级别
运行参数优化
- num-executors
- 参数说明:Executor进程数
- 优化建议:一般设置50~100个左右
- executor-memory
- 参数说明:Executor进程内存。决定Spark作业的性能;和OOM异常有直接的关联
- 优化建议:设置4G~8G较为合适。num-executors * executor-memory不能超过队列的最大内存量。共享资源队列时最好不要超过资源队列最大总内存的1/3~1/2
- executor-cores
- 参数说明:Executor进程CPU core数量。决定每个Executor进程并行执行task线程的能力
- 优化建议:设置为2~4个较为合适。共享队列时,num-executors * executor-cores不要超过队列总CPU core的1/3~1/2左右比较合适。最好一个cpu core对应两到三个task
- driver-memory
- 参数说明:Driver进程内存
- 优化建议:不设置或者设置1G左右。如果需要使用collect算子将RDD的数据全部拉取到Driver上进行处理,那么必须确保Driver的内存足够大,否则会出现OOM内存溢出的问题
- spark.default.parallelism
- 参数说明:stage的默认task数量。一个分区对应一个task,其实就是设置task的数量
- 优化建议:500~1000个较为合适。默认是一个HDFS block对应一个task。设置该参数为num-executors * executor-cores的2~3倍较为合适
- spark.storage.memoryFraction
- 参数说明:RDD持久化数据在Executor内存中能占的比例,默认是0.6
- 优化建议:如果Spark作业中,有较多的RDD持久化操作,该参数的值可以适当提高一些,保证持久化的数据能够容纳在内存中。避免内存不够缓存所有的数据,导致数据只能写入磁盘中,降低了性能。但是如果Spark作业中的shuffle类操作比较多,而持久化操作比较少,那么这个参数的值适当降低一些比较合适。此外,如果发现作业由于频繁的gc导致运行缓慢(通过spark web ui可以观察到作业的gc耗时),意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。
- spark.shuffle.memoryFraction
- 参数说明:shuffle过程中task拉取到上个stage的task的输出后,进行聚合操作时能够使用的Executor内存的比例,默认是0.2。shuffle操作在进行聚合时,如果发现使用的内存超出了这个20%的限制,那么多余的数据就会溢写到磁盘文件中去,此时就会极大地降低性能
- 优化建议:如果Spark作业中的RDD持久化操作较少,shuffle操作较多时,建议降低持久化操作的内存占比,提高shuffle操作的内存占比比例;如果发现作业由于频繁的gc导致运行缓慢,意味着task执行用户代码的内存不够用,那么同样建议调低这个参数的值。