hadoop 核心注意事项 小总:maptask并行机制 reduce并行机制 task并行 数据倾斜 shuffle

标题hadoop 核心注意事项 小总

一 .maptask的并行机制(逻辑切片)
maptask 的数量取决于 一般取决于 切片的数量。有多少切片就有多少maptask。
maptask 的数量主要取决于三个方面:
1.文件的大小及数量。
2.blocksize的大小
3.以及splip(块) size 大小

时间:是在mr客户端提交程序到yarn之前。
地点:mr程序客户端(main方法)
参与者:输入目录 FileInputFormat.getSplit();
规则是:对待处理的文件卓个遍历 一切片大小(blocksize)对文件进行逻辑切片
split size=blocksize=128m;
默认 :134217728b(128M) 【hadoop 官网说 默认是字节 也可以以 k(kilo),m(兆),g,t,p,e结尾如:128m,521m,1g】(hdfs-default.xml)

hadoop 核心注意事项 小总:maptask并行机制 reduce并行机制 task并行 数据倾斜 shuffle
举例正常切:
hadoop 核心注意事项 小总:maptask并行机制 reduce并行机制 task并行 数据倾斜 shuffle
源码中 fileinputformat 中 有一行代码:
Math.max(minSize,math.min(maxsize,blocksize))
这个很重要
不管如何调整,都不可能跨文件处理数据。卓个遍历
调整方向 :split size= block size ;

特殊情况1:小文件场景
1.txt 12k;
2.txt 10k;
3.txt 15k;
由于 默认规则是卓个遍历 ,这就导致了 会有 三个 split (这样太浪费资源,因为交个一个maptask 就可以了)

解决方案
1.(将小文件合并为一个文件)hdfs 有个追加命令 appendToFile +shell
2.可以使用java程序 以读写流的形式 将文件合并。
3.修改源码(修改默认读取数据组件逻辑)。

特殊情况2:大文件场景
1.txt 1.5t;
2.txt 3t;
如果我们使用默认的切片大小 :128m 我们会切成很多个split (块)
解决方案:
更改默认的blocksize =512m 或者更大

更改的位置:应该在 hdfs-site.xml 中 添加
property>
name>dfs.blocksize</name
value>512m</value
</property

特殊情况3:当使用默认blocksize=128m时且 有个文件1.txt 大小为 129M
按照我们的规则 将会切成 0-128m;128m-129m 俩个块。但是实际中并不是。
因为源码中 有行代码:bytesRemaining/splitSize>SPLIT_SLOP(常量1.1);
意思是:剩下的文件大小 /切片大小>1.1 如果满足条件 继续切 如果不满足剩下的所有作为一个切片。
129/128=1.0078<1.1
所以时间上 129m文件 就是一个切片。

特殊情况4:就是切的时候 将一个单词 切成了俩块 并在不同的split(块)中。
产生的原因:hdfs 在分块存储的时候 不会考虑数据的完整性 只要满足128M就会切开。
其实maptask 内部机制 已经帮我们考虑到这种情况。 【每个maptask读取数据的时候会额外读取下一个切片的第一行。如果自己不是第一个切片的话】
直白话:满足128m 就切 可能将一个单词 ha oop 切开,maptask 读取数据 textinputformat 是一行一行读的,每行都有 /n/r 换行符。只要我们多读下一个切片(块)的第一行 我们就能保证 hadoop.

二 reducetask 并行机制。
reducetask 的并行数量取决于job.setNumReduceTasks(n);
n为几就有几个reducetask
但是reducetask的数量不是任意设置的,如果分区数>n,则会报异常。如果分区<n,则会产生空文件。

同时如果不同的reducetask 上数据分布的不均匀 会造成数据倾斜问题。

数据倾斜:在并行处理数据的过程中,某些分区或者节点处理的数据明显多于其他分区或者节点处理的数据,也就是说 数据分配的不均匀,造成了数据倾斜问题。

数据倾斜危害:
1.任务长时间挂起,资源利用率下降。因为:计算作业一般是分阶段进行,阶段与阶段之间数据上通常存在依赖关系。也就是说 后一个阶段需要等待前一个阶段执行完成之后才能开始。
2.引发内存溢出 ,导致任务失败。因为:在发生数据倾斜时,可能导致大量的数据集中在少数的节点上,导致数据超出了单个节点的数据承受范围(内存被撑爆),最终导致内存溢出 报 oom异常。
3.作业执行时间超出预期时间,导致后续依赖数据结果的作业出错。因为:有时候作业与作业之间,并没有构建强依赖关系,而是通过执行时间的前后时间差来调度,当前置作业未在预期时间范围内完成执行,那么当后续作业启动时便无法读取到其所需要的最新数据,从而导致连续出错

哪些情况会造成数据倾斜呢?:
1.读入数据的时候就是倾斜的。也就是数据源倾斜。
2.shuffle产生倾斜。比如:特定的key值数据量 数据量过多,导致join发生,使大量数据涌入单个节点,使单个节点读写压力较大 容易发生 (内存溢出) oom异常。

shuffle概念解说:

shuffle 描述的是mr中的一个过程,
从map方法输出数据开始到reduce方法处理数据之前的所有阶段称之为shuffle。
shuffle阶段是mr的核心 横跨了mapper和reducer两个阶段 也可以说mr处理数据效
率低下的原因就是shuffle阶段过于繁琐 涉及了数据从内存到磁盘(map阶段的溢出)、磁盘到内存(reduce拉取数据)、 内存再到磁盘(reduce合并数据的过程)的阶段。

3.过滤导致倾斜: 比如数据源本来是均衡的,但经过过滤之后,某些节点过滤了少量的数据,有的节点过滤了大量的数据 这样也会导致数据倾斜问题。最终导致 oom异常。

如何解决数据倾斜问题呢?:

1.尽量保证数据源 是均衡的。【】
2…对大数据集做过滤,结束后做repartition。
对比较大的数据集做完过滤后,如果过滤掉了绝大部分数据,在进行下一步操作前,最好可以做一次repartition,让数据重回均匀分布的状态,否则失衡的数据集,在进行后续计算时,可能会逐渐累积倾斜的状态,容易产生错误。
3.对小表进行广播。
如果两个数据量差异较大的表做join时,发生数据倾斜的常见解决方法,是将小表广播到每个节点去,这样就可以实现map端join,从而省掉shuffle,避免了大量数据在个别节点上的汇聚,执行效率也大大提升。
4.编码时要注意,不要人为造成倾斜。
5.join前优化。
两个表join,某些特殊key值可能很多,很容易产生数据倾斜,这时可以根据实际计算进行join前优化。
如计算是先join后根据key聚合,那可以改为先根据key聚合然后再join。又如,需求是join后做distinct操作,在不影响结果的前提下,可以改为先distinct,然后再join。这些措施都是可以有效避免重复key过多导致join时倾斜。
6.具体问题具体分析。
读入mysql数据时倾斜,这通常是由于mysql的id分布严重不均,中间存在跨度很大的区间造成的。解决方法有两种,一是加大读取时的分区数,将倾斜的区间划分开;另一种是,先把id取出来进行等宽切割,确保每个区段的id数量一致,之后再对各区间进行数据读取。