标题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)

举例正常切:

源码中 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,则会产生空文件。所以分区数最好与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合并数据的过程)的阶段。
同时shuffle 可以分成 6个阶段:
1.Collect 阶段:将 MapTask 的结果输出到默认大小为 100M 的环形缓冲区,
保存的是 key/value,Partition 分区信息等
2.Spill 阶段(溢出):当内存中的数据量达到一定的阀值的时候,就会将数据写
入本地磁盘,在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置
了 combiner,还会将有相同分区号和 key 的数据进行排序。【80% 阈值,缓冲区达到80%就溢出 写去文件,剩下20%部分继续做存储】
3.Merge 阶段: 将溢出的小文件合并。保证maptask 阶段最终产生一个中间数据文件。
4.copy 阶段:reducetask 会将上面maptask数据copy 到对应分区 并先保存在缓冲区中,也是达到阈值再写到磁盘。
5.Merge 阶段:在 ReduceTask 远程复制数据的同时,会在后台开启两个线
程对内存到本地的数据文件进行合并操作。
6.sort阶段:对数据进行排序。在对数据进行合并的同时,会进行排序操作,由于 MapTask阶段已经对数据进行了局部的排序,ReduceTask 只需保证 Copy 的数据的最终整体有效性即可。
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数量一致,之后再对各区间进行数据读取。
三 task 并行度 经验之谈
保证每个task 运行的时间至少不少于1分钟。【不管是map task 还是reduce task】
因为 如果一个job中的map task 或者 reduce task 运行的时间 都只有30-40秒 则实际处理数据的时间只有 1-2秒 更多的时间是 在做资源的申请 释放 和沟通。【也就是说我们好不容易申请了资源 只做了类似看一眼就走的操作 这相当浪费资源】
如何测试执行多长时间呢 ? mapper 中 setup () 开始 clearup() 结束。
jvm 重用 这个点先不讲。
如果 input 的文件非常的大,比如 1TB,可以考虑将 hdfs 上的每个 block
size 设大,比如设成 256MB 或者 512MB
四 mapreduce 参数的优化。
在dirve 类中 conf.set(name,local) 设置
(1) mapreduce.map.memory.mb: 一个 Map Task 可使用的内存上限(单位:MB),默认为 1024。【maptask 可使用的内存 默认是1G 如果数据量比较大的情况下 我们可以设置大点】 如果 Map Task 实际使用的资源量超过该值,则会被强制杀死。
(2) mapreduce.reduce.memory.mb: 一个 Reduce Task 可使用的资源上限(单位:MB),默认为 1024。如果 Reduce Task 实际使用的资源量超过该值,则会被强制杀死。【reducetask 可使用的内存 默认是1G如果数据量比较大的情况下 我们可以设置大点】
(3) mapreduce.map.cpu.vcores: 每个 Maptask 可用的最多 cpu core 数目, 默认值: 1【使用cpu 核数 默认1 这要看你的服务器 比如16核32线程】
(4) mapreduce.reduce.cpu.vcores: 每个 Reducetask 可用最多 cpu core 数目默认值:1【使用cpu 核数 默认1 这要看你的服务器 比如16核32线程】
(5) mapreduce.map.java.opts: Map Task 的 JVM 参数,你可以在此配置默认的 java heap
size 等参数, 例如:“-Xmx1024m -verbose:gc -Xloggc:/tmp/@taskid@.gc”
(@taskid@会被 Hadoop 框架自动换为相应的 taskid), 默认值: “”
(6) mapreduce.reduce.java.opts: Reduce Task 的 JVM 参数,你可以在此配置默认的 java
heap size 等参数, 例如:“-Xmx1024m -verbose:gc -Xloggc:/tmp/@taskid@.gc”, 默
认值: “”
五 容错相关参数配置
(1) mapreduce.map.maxattempts: 每个 Map Task 最大重试次数,一旦重试参数超过该值,则
认为 Map Task 运行失败,默认值:4。 【就是说有一个maptask 失败一次 并不代表最终失败,重复执行4次后还是失败 才是真的失败】
(2) mapreduce.reduce.maxattempts: 每个Reduce Task最大重试次数,一旦重试参数超过该值,
则认为 Map Task 运行失败,默认值:4。【就是说有一个reducetask 失败一次 并不代表最终失败,重复执行4次后还是失败 才是真的失败】
(3) mapreduce.map.failures.maxpercent: 当失败的 Map Task 失败比例超过该值,整个作业则
失败,默认值为 0. 如果你的应用程序允许丢弃部分输入数据,则该该值设为一个大于 0 的
值,比如 5,表示如果有低于 5%的 Map Task 失败(如果一个 Map Task 重试次数超过
mapreduce.map.maxattempts,则认为这个 Map Task 失败,其对应的输入数据将不会产生任
何结果),整个作业扔认为成功。【默认是0 不允许任何一个 maptask失败,如果设置为 5 则代表 就是说 允许5%的maptask失败 超过5%的失败则代表整体失败】
(4) mapreduce.reduce.failures.maxpercent: 当失败的 Reduce Task 失败比例超过该值为,整个
作业则失败,默认值为 0. 【默认是0 不允许任何一个 reducetask失败,如果设置为 5 则代表 就是说 允许5%的maptask失败 超过5%的失败则代表整体失败】
(5) mapreduce.task.timeout:如果一个task在一定时间内没有任何进入,即不会读取新的数据,
也没有输出数据,则认为该 task 处于 block 状态,可能是临时卡住,也许永远会卡住。为了
防止因为用户程序永远 block 不退出,则强制设置了一个超时时间(单位毫秒),默认是
600000(10分钟),值为 0 将禁用超时。。 【task 超时时间 默认10分钟 ,就是说一个task 在10分钟内 没有任何读或者写操作 就将kill 掉 防止task 被锁死(block)】
六 mapreduce 的计时器 (Counter)
mapreduce 内置计时器有:【就是我们运行一个mr程序后 控制台 出现的一些数据】
文件系统计数器(File System Counters)
作业计数器(Job Counters)
MapReduce 框架计数器(Map-Reduce Framework)
Shuffle 错误计数器(Shuffle Errors)
文件输入格式计数器(File Output Format Counters)
文件输出格式计数器(File Input Format Counters)
这里重点 讲下 mapreduce 的自定义 计时器:
在实际生产代码中,常常需要将数据处理过程中遇到的不合规数据行进行全局计数类似这种需求可以借助mapreduce 框架中提供的全局计数器来实现。【就是保证一个变量 全局有效,如何保证呢 mapreduce 框架中给我们提供了 全局计时器 我们只需要 自定义我们的组名 和计数器的名字】


本文总结了Hadoop核心注意事项,包括maptask并行机制的逻辑切片原理及其特殊情况处理,reduce并行机制与数据倾斜问题的影响和解决方案,以及mapreduce参数优化和自定义计时器的使用。讨论了maptask和reducetask的并行度、shuffle过程、任务容错参数,提供了一些建议以提高Hadoop作业的效率和稳定性。
1994

被折叠的 条评论
为什么被折叠?



