Spark shuffle流程细则

  1. hadoop中的shuffle存在map任务和reduce任务之间,而spark中的shuffle过程存在stage之间。
  2. shuffle操作分为两种,分别是写操作和读操作。
  3. shuffle的写操作包括两种,分别是基于哈希的shuffle操作和基于排序的shuffle写操作。在spark1.2版本之前,采用基于哈希的shuffle操作,1.2版本之后采用基于排序的shuffle写操作。
    • 基于哈希的shuffle操作:基于哈希的shuffle操作的原理在于将Mapper(stage)生成的中间数据,按照Reduce的数量(Reduce任务的数量取决于当前stage的RDD的分区数量)进行切分。切分成多个bucket,每个bucket对应一个文件。当reduce任务运行时,会根据任务的编号和所依赖的mapper编号远程或者从本地取得相应的bucket作为reduce任务的输入数据进行处理。
    • 基于排序的shuffle操作: 基于哈希的shuffle操作会产生很多文件,这对文件系统来说是一个非诚大的负担,而且在总数据量不大而文件特别多的情况下,随机读写会严重降低I/O性能。大量文件的带来的问题还包括缓存。缓存所占用的内存过多是一笔很大的开销。每个shuffle map task只会产生一个单独的文件,以及这个文件的索引,其中索引中 记载着,这个文件的那些数据是被下游的那些reduce task任务使用。
  4. shuffle的读操作(拉取数据)
    • 从前面可以知道,shuffle的写操作有两种方式,但是在读操作中,将根据不同的写入方式采取相同的读取方式,读取的数据放在哈希列表中用于后续处理。
    • 流程:
      • 起始点是ShuffleRDD.computer()发起,在该方法中会调用ShuffleManager的getReader方法。shuffleManager是在SparkEnv启动的时候被实例化的,一起被实例化的还包括ShuffleManager、BlockManager、MapOutputTracker(读取数据时,用来首先获取元数据时使用)等。
      • shuffleManager的getReader()是采用的HashShuffleReader或者SortShuffleReader的read方法(这两种方法均会实例化BlockStoreShuffleReader)。在HashShuffleReader.read()方法中,先实例化ShuffleBlockFetchIterator(位于BlockStoreShuffleReader中),在实例化的过程中,获取上游ShuffleMapTask输出数据的元数据
      • 得到元数据后,返回ShuffleBlockFetchIterator中的initialize方法,通过splitLocalRemoteBlocks方法对获取的数据位置信息进行区分,来判断数据的位置是本地节点还是远程节点。不同的位置采用不同的方法来获取数据,远程节点上的数据利用fetchUpToMaxBytes方法,本地数据利用fetchLoalBlocks方法获取。
      • 数据读取完毕,回到BlockStoreShuffleReader的read方法,判断是否定义聚合。如果需要,则根据键值进行聚合。聚合完毕后,使用外部排序(ExternalSorter)对数据进行排序并放入内存.
      • 读取数据后,判断ShuffleDependency是否定义聚合,如果需要,则根据键值进行聚合。数据聚合完毕后,对数据进行排序。

如何确定reduce任务个数

你可能感兴趣的:(Spark shuffle流程细则)