这是我参与「第四届青训营 」笔记创作活动的的第4天
-
MapReduce 概述
当今项目往往有较大的数据量,单机无法处理全部数据,只能将数据分割成小块在多个单机内并发处理。其中,map是将相同类型的数据分类,shuffle则主要将同类型的数据组合(在map的基础上进行数据移动)。
-
Spark 与 Shuffle
spark中把shuffle抽象成了宽依赖和窄依赖。当出现宽依赖时,spark会把数据拆分成两个stage,map和reduce。
-
partitioner
负责把key映射成数字。有numberPartitions和getPartition两个接口。
-
Aggregator
Aggregtor被称为重要的性能优化器,可以计算重复出现的字符串。我理解的是,aggregator类似一个hashmap,,它是以map 输出的key为key,以需要combine的类型为value的hashmap。它会将Shuffle map后每一个key-value对更新或是插入到hashmap中更新value,省去了对相同字符串排序的时间。
-
读取
每个reduce task分别获取所有map task生成的属于自己的片段。
-
shuffle handle & writer
根据情景不同,创建不同的shuffle。
不同的shuffle handle对应不同的writer。
-
BypassMergeShuffleWriter:不用排序,节省cpu,类似于Hash shuffle(最终会merge文件)。
-
UnsafeShuffleWriter:数据排序后不再反序列化。使用类似内存页储存序列化数据。
-
SortShuffleWriter:需要combine的时候是hashtable,不需要combine的时候本质是array。
-
Reader
这一块我读了一篇知乎文章加以补充。
-
创建一个能够获取多个数据块的迭代器:ShuffleBlockFetcherIterator对象,它可以区分local和remote节省网络消耗。防止OOM。
-
获取一个序列化器对象:serializerInstance
-
遍历第1)把数据还原成key/value的形式,从而得到一个key/value的迭代器。
-
更新任务的metrics值.
-
为了支持任务的取消,需要创建一个可中断的迭代器,来读取数据。
-
若有聚合操作,会判断是否已经在map进行了聚合,若是则读取的是已经聚合好的数据;若没有在map端进行聚合,则会先通过ExternalAppendOnlyMap来对数据进行聚合。若没有聚合操作,则直接返回数据的迭代器。
-
若有排序操作,会创建一个ExternalSorter类的对象,通过对象来对数据进行排序,然后把排好序的结果保存到结果迭代器中。
-
Zero copy
数据直接从内核缓冲区直接送入Socket缓冲区。减少上下文切换次数。
-
Netty Zero copy
可堆外内存,避免JVM堆内存到堆外存到数据拷贝。可以合并包装,切分数组,避免发生内存拷贝。