数据本地化对于spark job 性能 有着巨大的影响,如果数据以及要计算它的代码是在一起的那么性能会相当的高。但是如果数据和代码是分开的,那么其中之一必须到另外一方的机器上。通常来说移动代码到其他的节点,会比移动数据到其他的节点的速度要快的多,因为代码较小。spark也正是基于这个数据本地化的原则来构建task调度算法的。
数据本地化,指的是,数据离计算他的代码有多近。基于数据离代码的距离,有几种本地化的级别。
1.PROCESS_LOCAL 数据和计算他的代码在一个JVM进程中。
2.NODE_LOCAL :数据和计算他的代码在一个节点上,但是不在一个进程中,比如不同的executor进程中,或者是数据在hdfs的block中。
3.NO_PREF :数据从那里过来性能都是一样的
4.RACK_LOCAL 数据和计算他的代码在一台机器上
5.ANY 数据在任何地方,比如其他网络环境内或者其他的机器上。

下面给出一个图解关于

TaskScheculeImpl 调度task 本地化

spark本地级别 spark数据本地化级别_性能优化


Task要处理的partition 的数据,在某一个Executor中,然后TaskScheduleImpl 首先会尽量用最好的本地化级别去启动task。也就是说,会尽量在那个包含要处理的partition的executor中去启动task.

但是此时呢executor已经在执行好几个task了没有空闲的资源来调度task.

默认情况下,spark会等待一会儿,等待executor 什么时候可以空闲出一个cpu core从而启动这个task.让它来实现本地化级别,但是如果等待了一会儿(时间是可以通过参数设置),发现始终没有等待execulor的core 释放。那么就会放大一个级别来启动这个task。

比如说,rdd之前就持久化task.会去调用RDD,的iterator()方法,然后通过executor。关联blockManager来尝试获取数据。blockManager首先尝试使用getLocal()获取数据如果没有找到的化那么用getRemote ,通过BlockTransferService连接到有数据的executor获取数据。

如果没有持久化computeOrReadCheckPoint().

spark倾向于使用最好的本地化级别来调度task,但是这个是不可能的如果没有任何未处理的数据在空闲的executor的上,那么spark就会放低本地化级别,这个时候有两个选择一个是继续等待等到有一个executor被释放出来,立即在任意一个executor 上面去启动一个task.
spark等待一会期望task来处理的数据所在的节点上的executor空出一个cpu,从而将task分配过去。只要超过了时间,那么spark 就会将task分配到其他任意一个空闲的executor上。
可以设置参数,spark.locatity系列,来调节spark等待task可以进行数据本地化的时间。
spark.locatity.wait(3000) 。(毫秒)
spark.localtity.wait.node
spark.locatity.wait.process
spark.locatity.wait.rack