Hadoop测试
集群搭建起来,是不是就万事大吉了呢?如果只是用来学习或者做做实验,貌似够了,但生产环境中还不够,因为我们还没有对集群进行测试,是不是能达到我们预期。
1.1写测试
测试写入100个128M的文件
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -write -nrFiles 100 -fileSize 128MB
1.2.读测试
测试读100个128的文件
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -read -nrFiles 100 -fileSize 128MB
1.3删除测试数据
测试数据必须删除,不能带到生产中
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -clean
1.4 用Sort评估MapReduce
1)使用RandomWriter来产生随机数,每个节点运行10个Map任务,每个Map产生大约1G大小的二进制随机数
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar randomwriter random-data
2)执行sort
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar sort random-data sorted-data
3)验证结果
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar testmapredsort -sortInput random-data -sortOutput sorted-data
哈哈,我的电脑不给力,没法直接演示,看来要升级了。
决定进入大数据坑的同学,电脑配置得高点,不然带不动。
2.Hadoop性能调优
集群测试,不符合预期,那就要进入性能调优了。
2.1 MpaReduce的优化
MapReduce执行效率的瓶颈在两个方面
1.计算机性能影响,像CPU、内存大小、磁盘、网络延迟。
2.IO方面的优化情况
1)数据倾斜问题
2)Map和Reduce的个数设置情况
3)Map耗时太长
4)小文件太多
5)Spill和Merge次数太多等等
我们对MapReduce的优化大致是六个方面
1)数据输入
2)Map阶段
3)Reduce阶段
4)IO传输
5)数据倾斜
6)参数调优
2.1.1 数据输入
例如合并小文件,我们都知道小文件会产生大量的MapTask,所以我们可以在执行MR任务前,先进行小文件的合并。
默认情况下TextInputformat对任务的切片机制是按文件规划切片,不管文件多小,都会有一个单独的切片,都会交给一个maptask,如果有大量的小文件,就会产生大量的maptask,处理效率及其低下
我们可以改用CombineTextInputFormat,解决输入端大量小文件的问题。
2.1.2 Map阶段
1.减少Spill次数,也就是溢写次数:通过调整io.sort.mb及sort.spill.percent参数值,增大触发Spill的内存上限,减少Spill次数,从而减少磁盘IO。
2.减少Merge次数:通过调整io.sort.factor参数,增大Merge的文件数目,减少Merge的次数,从而缩短MR处理时间。
3.Map之后,在不影响业务逻辑前提之下,可以先进行Combine,减少IO。
2.1.3 Reduce阶段
1.Map和Reduce个数的设置:两个不能设置太少,也不能太多。
太少,会导致Task等待,延长处理时间;
太多,会导致Map、Reduce任务间竞争资源,造成处理超时等错误。
2.Map、Reduce共存:调整slowstart.completedmaps参数,使Map运行到一定程度后,Reduce也开始运行,减少Reduce的等待时间。
3.规避使用Reduce:因为Reduce在用于连接数据集的时候将会产生大量的网络消耗。
2.1.4 IO传输
1)数据压缩
2)使用SequenceFile二进制文件
2.1.5 数据倾斜
什么是数据倾斜?
简单来说就是大量的相同key被partition分配到一个分区里,造成了'一个人累死,其他人闲死'的情况。
解决方法:
1)自定义分区,也就是Partition,指定分区策略
2)重新设计key,例如在map阶段给key加一个随机值,有了随机值的key就不会有大概率的机会被大量分到同一个节点上了,到了reduce阶段,在把随机值去掉。
3)使用Combine,Combinner是在map阶段,reduce之前的一个中间阶段,在这个阶段可以选择性的把大量的相同key数据先进行一个合并,可以看做是local reduce,然后再交给reduce来处理,这样做的好处很多,即减轻了map端向reduce端发送的数据量(减轻了网络带宽),也减轻了map端和reduce端中间的shuffle阶段的数据拉取数量(本地化磁盘IO速率)
解决方法也不止上面所述,具体也要根据实际情况来说。
2.1.6 调优参数
1)以下参数是在用户自己的MR应用程序中配置就可以生效(mapred-default.xml)
配置参数 | 参数说明 |
---|---|
mapreduce.map.memory.mb | 一个MapTask可使用的资源上限(单位:MB),默认为1024。如果MapTask实际使用的资源量超过该值,则会被强制杀死。 |
mapreduce.reduce.memory.mb | 一个ReduceTask可使用的资源上限(单位:MB),默认为1024。如果ReduceTask实际使用的资源量超过该值,则会被强制杀死。 |
mapreduce.map.cpu.vcores | 每个MapTask可使用的最多cpu core数目,默认值: 1 |
mapreduce.reduce.cpu.vcores | 每个ReduceTask可使用的最多cpu core数目,默认值: 1 |
mapreduce.reduce.shuffle.parallelcopies | 每个Reduce去Map中取数据的并行数。默认值是5 |
mapreduce.reduce.shuffle.merge.percent | Buffer中的数据达到多少比例开始写入磁盘。默认值0.66 |
mapreduce.reduce.shuffle.input.buffer.percent | Buffer大小占Reduce可用内存的比例。默认值0.7 |
mapreduce.reduce.input.buffer.percent | 指定多少比例的内存用来存放Buffer中的数据,默认值是0.0 |
2)应该在YARN启动之前就配置在服务器的配置文件中才能生效(yarn-default.xml)
配置参数 | 参数说明 |
---|---|
yarn.scheduler.minimum-allocation-mb | 给应用程序Container分配的最小内存,默认值:1024 |
yarn.scheduler.maximum-allocation-mb | 给应用程序Container分配的最大内存,默认值:8192 |
yarn.scheduler.minimum-allocation-vcores | 每个Container申请的最小CPU核数,默认值:1 |
yarn.scheduler.maximum-allocation-vcores | 每个Container申请的最大CPU核数,默认值:32 |
yarn.nodemanager.resource.memory-mb | 给Containers分配的最大物理内存,默认值:8192 |
3)Shuffle性能优化的关键参数,应在YARN启动之前就配置好(mapred-default.xml)
配置参数 | 参数说明 |
---|---|
mapreduce.task.io.sort.mb | Shuffle的环形缓冲区大小,默认100m |
mapreduce.map.sort.spill.percent | 环形缓冲区溢出的阈值,默认80% |
4)容错相关参数(MapReduce性能优化)
配置参数 | 参数说明 |
---|---|
mapreduce.map.maxattempts | 每个Map Task最大重试次数,一旦重试参数超过该值,则认为Map Task运行失败,默认值:4。 |
mapreduce.reduce.maxattempts | 每个Reduce Task最大重试次数,一旦重试参数超过该值,则认为Map Task运行失败,默认值:4。 |
mapreduce.task.timeout | Task超时时间,经常需要设置的一个参数,该参数表达的意思为:如果一个Task在一定时间内没有任何进入,即不会读取新的数据,也没有输出数据,则认为该Task处于Block状态,可能是卡住了,也许永远会卡住,为了防止因为用户程序永远Block住不退出,则强制设置了一个该超时时间(单位毫秒),默认是600000。如果你的程序对每条输入数据的处理时间过长(比如会访问数据库,通过网络拉取数据等),建议将该参数调大,该参数过小常出现的错误提示是“AttemptID:attempt_14267829456721_123456_m_000224_0 Timed out after 300 secsContainer killed by the ApplicationMaster.”。 |
2.2 小文件的问题
为什么HDFS怕小文件呢?
因为HDFS上每个文件都要在NameNode建立一个索引,这个索引大小约150byte,当大量小文件时,就会产生很多的索引文件,但内存是有限制的,另外索引文件过大也会使得索引查询效率降低。
所以小文件问题,在生产环境中一定要引起注意的问题。
解决方式就是减少小文件产生或者对小文件合并,具体有以下几种方式:
1)在数据采集的时候,就将小文件或小批数据合成大文件再上传HDFS。
2)在业务处理之前,在HDFS上使用MapReduce程序对小文件进行合并。
3)在MapReduce处理时,可采用CombineTextInputFormat提高效率。