Spark - 性能优化详解5(数据本地化)
作者:hangge | 2024-07-31 09:58
五、数据本地化
1,基本介绍
(1)数据本地化,指的是数据离计算它的代码有多近。数据本地化对于 Spark Job 性能有着巨大的影响。
- 如果数据以及要计算它的代码是在一起的,那么性能当然会非常高。
- 但是,如果数据和计算它的代码是分开的,那么其中之一必须到另外一方的机器上。
(2)通常来说,移动代码到其它节点,会比移动数据到代码所在的节点速度要得多,因为代码比较小。Spark 也正是基于这个数据本地化的原则来构建 task 调度算法的。
2,Spark 的数据本地化策略
(1)具体来说,有几种数据本地化级别:
- PROCESS_LOCAL:进程本地化,性能最好,数据和计算它的代码在同一个 JVM 进程中。
- 这种情况是 RDD 的数据经过缓存,此时不需要网络传输,是最优 locality。(但是数据要先缓存)。
- NODE_LOCAL:节点本地化,数据和计算它的代码在一个节点上,但是不在一个 JVM 进程中,数据需要跨进程传输。具体分两种情况:
- 一是数据和 Task 在同一节点上的不同 executor 中;
- 二是数据 HDFS 和 Task 在同一个结点上
- NO_PREF:数据从哪里过来性能都是一样的,比如从数据库中获取数据,对于 task 而言没有区别
- RACK_LOCAL:数据和计算它的代码在一个机架上,数据需要通过网络在节点之间进行传输
- ANY:数据可能在任意地方,比如其它网络环境内,或者其它机架上,性能最差
(2)Spark 倾向使用最好的本地化级别调度 task,但这是不现实的。如果我们要处理的数据所在的 executor 上目前没有空闲的 CPU,那么 Spark 就会放低本地化级别。这时有两个选择:
- 第一,等待,直到 executor 上的 cpu 释放出来,那么就分配 task 过去;
- 第二,立即在任意一个其它 executor 上启动一个 task。
(3)Spark 默认会等待指定时间,期望 task 要处理的数据所在的节点上的 executor 空闲出一个 cpu,从而将 task 分配过去,只要超过了时间,那么 Spark 就会将 task 分配到其它任意一个空闲的 executor 上。我们可以设置 spark.locality 系列参数,来调节 Spark 等待 task 可以进行数据本地化的时间:
- spark.locality.wait:为了数据本地性最长等待时间,默认等待 3 秒(3000 毫秒)
- spark.locality.wait.process:等待指定的时间看能否达到数据和计算它的代码在同一个 JVM 进程中(默认值为 spark.locality.wait)
- spark.locality.wait.node:等待指定的时间看能否达到数据和计算它的代码在一个节点上执行(默认值为 spark.locality.wait)
- spark.locality.wait.rack:等待指定的时间看能否达到数据和计算它的代码在一个机架上(默认值为 spark.locality.wait)
3,样例演示
(1)当任务提交并执行后,查看 Spark Web UI 任务信息,我们可以看到下面的信息。其中 Locality Level 一栏就是数据本地性的情况。如果大多都是 PROCESS_LOCAL,那就不用调节了。如果是发现,好多的级别都是 NODE_LOCAL、ANY,那么最好就去调节一下数据本地化的等待时长。
(2)我们可以直接在任务代码中进行等待时长的设置:
val conf = new SparkConf().set("spark.locality.wait","10")
(3)也可以在 spark-submit 脚本中通过 --conf 参数设置动态设置:
./bin/spark-submit \ --class MoreParallelismScala \ --master yarn \ --deploy-mode cluster \ --conf "spark.locality.wait=10s" \ spark-1.0-SNAPSHOT-jar-with-dependencies.jar
全部评论(0)