Hadoop优化 第一篇 : HDFS/MapReduce
比较惭愧,博客很久(半年)没更新了。最近也自己搭了个博客,wordpress玩的还不是很熟,感兴趣的朋友可以多多交流哈!地址是:http://www.leocook.org/
另外,我建了个QQ群:305994766,希望对大数据、算法研发、系统架构感兴趣的朋友能够加入进来,大家一起学习,共同进步(进群请说明自己的公司-职业-昵称)。
1.应用程序角度进行优化
1.1.减少不必要的reduce任务
若对于同一份数据需要多次处理,可以尝试先排序、分区,然后自定义InputSplit将某一个分区作为一个Map的输入,在Map中处理数据,将Reduce的个数设置为空。
1.2.外部文件引用
如字典、配置文件等需要在Task之间共享的数据,可使用分布式缓存DistributedCache或者使用-files
1.3.使用Combiner
combiner是发生在map端的,作用是归并Map端输出的文件,这样Map端输出的数据量就小了,减少了Map端和reduce端间的数据传输。需要注意的是,Combiner不能影响作业的结果;不是每个MR都可以使用Combiner的,需要根据具体业务来定;Combiner是发生在Map端的,不能垮Map来执行(只有Reduce可以接收多个Map任务的输出数据)
1.4.使用合适的Writable类型
尽可能使用二进制的Writable类型,例如:IntWritable, FloatWritable等,而不是Text。因为在一个批处理系统中将数值转换为文本时低效率的。使用二进制的Writable类型可以降低cpu资源的消耗,也可以减少Map端中间数据、结果数据占用的空间。
1.5.尽可能的少创建新的Java对象
a)需要注意的Writable对象,例如下面的写法:
public void map(...) {
…
for (String word : words) {
output.collect(new Text(word), new IntWritable());
}
}
这样会冲去创建对象new Text(word)和new IntWritable(1)),这样可能会产生海量的短周期对象。更高效的写法见下:
class MyMapper … {
Text wordText = new Text();
IntWritable one = new IntWritable();
public void map(...) {
for (String word: words) {
wordText.set(word);
output.collect(wordText, one);
}
}
}
b)对于可变字符串,使用StringBuffer而不是String
String类是经过final修饰的,那么每次对它的修改都会产生临时对象,而SB则不会。
2. Linux系统层面上的配置调优
2.1. 文件系统的配置
a) 关闭文件在被操作时会记下时间戳:noatime和nodiratime
b) 选择I/O性能较好的文件系统(Hadoop比较依赖本地的文件系统)
2.2. Linux文件系统预读缓冲区大小
命令blockdev
2.3. 去除RAID和LVM
2.4. 增大同时打开的文件数和网络连接数
ulimit
net.core.somaxconn
2.5. 关闭swap分区
在Hadoop中,对于每个作业处理的数据量和每个Task中用到的各种缓冲,用户都是完全可控的。
/etc/sysctl.conf
2.6. I/O调度器选择
详情见AMD的白皮书
3. Hadoop平台内参数调优
Hadoop相关可配置参数共有几百个,但是其中只有三十个左右会对其性能产生显著影响。
3.1. 计算资源优化
a) 设置合理的slot(资源槽位)
mapred.tasktracker.map.tasks.maximum / mapred.tasktracker.reduce.tasks.maximum
参数说明:每个TaskTracker上可并发执行的Map Task和Reduce Task数目
默认值:都是2
推荐值:根据具体的节点资源来看,推荐值是(core_per_node)/2~2*(cores_per_node)
单位:无
3.2. 节点间的通信优化
a) TaskTracker和JobTracker之间的心跳间隔
这个值太小的话,在一个大集群中会造成JobTracker需要处理高并发心跳,可能会有很大的压力。
建议集群规模小于300时,使用默认值3秒,在此基础上,集群规模每增加100台,会加1秒。
b) 启用带外心跳(out-of-band heartbeat)
mapreduce.tasktracker.outofband.heartbeat
参数说明:主要是为了减少任务分配延迟。它与常规心跳不同,一般的心跳是一定时间间隔发送的,而带外心跳是在任务运行结束或是失败时发送,这样就能在TaskTracker节点出现空闲资源的时候能第一时间通知JobTracker。
3.3. 磁盘块的配置优化
a) 作业相关的磁盘配置:mapred.local.dir
参数说明:map本地计算时所用到的目录,建议配置在多块硬盘上
b) 存储相关的磁盘配置(HDFS数据存储):dfs.data.dir
参数说明:HDFS的数据存储目录,建议配置在多块硬盘上,可提高整体IO性能
例如:
<property>
<name>dfs.name.dir</name>
<value>/data1/hadoopdata/mapred/jt/,/data2/hadoopdata/mapred/jt/</value>
</property>
c) 存储相关的磁盘配置(HDFS元数据存储):dfs.name.dir
参数说明:HDFS的元数据存储目录,建议设置多目录,每个多目录都可保存元数据的一个备份
注:要想提升hadoop整体IO性能,对于hadoop中用到的所有文件目录,都需要评估它磁盘IO的负载,对于IO负载可能会高的目录,最好都配置到多个磁盘上,以提示IO性能
3.4. RPC Handler个数和Http线程数优化
a) RPC Handler个数(mapred.job.tracker.handler.count)
参数说明:JobTracker需要并发的处理来自各个TaskTracker的RPC请求,可根据集群规模和并发数来调整RPC Handler的个数。
默认值:10
推荐值:60-70,最少要是TaskTracker个数的4%
单位:无
b) Http线程数(tasktracker.http.threads)
在Shuffle阶段,Reduce Task会通过Http请求从各个TaskTracker上读取Map Task的结果,TaskTracker是使用Jetty Server来提供服务的,这里可适量调整Jetty Server的工作线程以提高它的并发处理能力。
默认值:40
推荐值:50-80+
3.5. 选择合适的压缩算法
mapred.compress.map.output / Mapred.output.compress
map输出的中间结果时需要进行压缩的,指定压缩方式(Mapred.compress.map.output.codec/ Mapred.output.compress.codec)。推荐使用LZO压缩。
3.6. 启用批量任务调度(现在新版本都默认支持了)
a) Fair Scheduler
mapred.fairscheduler.assignmultiple
b) Capacity Scheduler
3.7. 启用预读机制(Apache暂时没有)
Hadoop是顺序读,所以预读机制可以很明显的提高HDFS的读性能。
HDFS预读:
dfs.datanode.readahead :true
dfs.datanode.readahead.bytes :4MB
shuffle预读:
mapred.tasktracker.shuffle.fadvise : true
mapred.tasktracker.shuffle.readahead.bytes : 4MB
3.8.HDFS相关参数优化
1) dfs.replication
参数说明:hdfs文件副本数
默认值:3
推荐值:3-5(对于IO较为密集的场景可适量增大)
单位:无
2) dfs.blocksize
参数说明:
默认值:67108864(64MB)
推荐值:稍大型集群建议设为128MB(134217728)或256MB(268435456)
单位:无
3) dfs.datanode.handler.count
参数说明:DateNode上的服务线程数
默认值:10
推荐值:
单位:无
4) fs.trash.interval
参数说明:HDFS文件删除后会移动到垃圾箱,该参数时清理垃圾箱的时间
默认值:0
推荐值:1440(1day)
单位:无
5) io.sort.factor
参数说明:当一个map task执行完之后,本地磁盘上(mapred.local.dir)有若干个spill文件,map task最后做的一件事就是执行merge sort,把这些spill文件合成一个文件(partition)。执行merge sort的时候,每次同时打开多少个spill文件由该参数决定。打开的文件越多,不一定merge sort就越快,所以要根据数据情况适当的调整。
默认值:10
推荐值:
单位:无
6) mapred.child.java.opts
参数说明:JVM堆的最大可用内存
默认值:-Xmx200m
推荐值:-Xmx1G | -Xmx4G | -Xmx8G
单位:-Xmx8589934592也行,单位不固定
7) io.sort.mb
参数说明:Map Task的输出结果和元数据在内存中占的buffer总大小,当buffer达到一定阀值时,会启动一个后台进程来对buffer里的内容进行排序,然后写入本地磁盘,形成一个split小文件
默认值:100
推荐值:200 | 800
单位:兆
8) io.sort.spill.percent
参数说明:即io.sort.mb中所说的阀值
默认值:0.8
推荐值:0.8
单位:无
9) io.sort.record
参数说明:io.sort.mb中分类给元数据的空间占比
默认值:0.05
推荐值:0.05
单位:无
10) Mapred.reduce.parallel
参数说明:Reduce shuffle阶段copier线程数。默认是5,对于较大集群,可调整为16~25
默认值:5
推荐值:16~25
单位:无
4.系统实现角度调优
https://www.xiaohui.org/archives/944.html
主要针对HDFS进行优化,HDFS性能低下的两个原因:调度延迟和可移植性
4.1. 调度延迟
关于调度延迟主要是发生在两个阶段:
a) tasktracker上出现空余的slot到该tasktracker接收到新的task;
b) tasktracker获取到了新的Task后,到连接上了datanode,并且可以读写数据。
之所以说这两个阶段不够高效,因为一个分布式计算系统需要解决的是计算问题,如果把过多的时间花费在其它上,就显得很不合适,例如线程等待、高负荷的数据传输。
下面解释下会经历上边两个阶段发生的过程:
a) 当tasktracker上出现slot时,他会调用heartbeat方法向jobtracker发送心跳包(默认时间间隔是3秒,集群很大时可适量调整)来告知它,假设此时有准备需要执行的task,那么jobtracker会采用某种调度机制(调度机制很重要,是一个可以深度研究的东东)选择一个Task,然后通过调用heartbeat方法发送心跳包告知tasktracker。在该过程中,HDFS一直处于等待状态,这就使得资源利用率不高。
b) 这个过程中所发生的操作都是串行化的:tasktracker会连接到namenode上获取到自己需要的数据在datanode上的存储情况,然后再从datanode上读数据,在该过程中,HDFS一直处于等待状态,这就使得资源利用率不高。
若能减短hdfs的等待时间;在执行task之前就开始把数据读到将要执行该task的tasktracker上,减少数据传输时间,那么将会显得高效很多。未解决此类问题,有这样几种解决方案:重叠I/O和CPU阶段(pipelining),task预取(task prefetching),数据预取(data prefetching)等。
4.2. 可移植性
Hadoop是Java写的,所以可移植性相对较高。由于它屏蔽了底层文件系统,所以无法使用底层api来优化数据的读写。在活跃度较高的集群里(例如共享集群),大量并发读写会增加磁盘的随机寻道时间,这会降低读写效率;在大并发写的场景下,还会增加大量的磁盘碎片,这样将会大大的增加了读数据的成本,hdfs更适合文件顺序读取。
对于上述问题,可以尝试使用下面的解决方案:
tasktracker现在的线程模型是:one thread per client,即每个client连接都是由一个线程处理的(包括接受请求、处理请求,返回结果)。那么这一块一个拆分成两个部分来做,一组线程来处理和client的通信(Client Threads),一组用于数据的读写(Disk Threads)。
想要解决上述两个问题,暂时没有十全十美的办法,只能尽可能的权衡保证调度延迟相对较低+可移植性相对较高。
4.3. 优化策略:Prefetching与preshuffling
a) Prefetching包括Block-intra prefetching和Block-inter prefetching:
Block-intra prefetching:对block内部数据处理方式进行了优化,即一边进行计算,一边预读将要用到的数据。这种方式需要解决两个难题:一个是计算和预取同步,另一个是确定合适的预取率。前者可以使用进度条(processing bar)的概念,进度条主要是记录计算数据和预读数据的进度,当同步被打破时发出同步失效的通知。后者是要根据实际情况来设定,可采用重复试验的方法来确定。
Block-inter prefetching:在block层面上预读数据,在某个Task正在处理数据块A1的时候,预测器能预测接下来将要读取的数据块A2、A3、A4,然后把数据块A2、A3、A4预读到Task所在的rack上。
b) preshuffling
数据被map task处理之前,由预测器判断每条记录将要被哪个reduce task处理,将这些数据交给靠近reduce task的map task来处理。
参考资料:
cloudera官方文档
http://blog.cloudera.com/blog/2009/12/7-tips-for-improving-mapreduce-performance/
AMD白皮书(较为实用)
http://www.admin-magazine.com/HPC/content/download/9408/73372/file/Hadoop_Tuning_Guide-Version5.pdf
国内博客(大部分内容都是AMD白皮书上的翻译):
http://dongxicheng.org/mapreduce/hadoop-optimization-0/
http://dongxicheng.org/mapreduce/hadoop-optimization-1/
Hadoop优化 第一篇 : HDFS/MapReduce的更多相关文章
- Hadoop实战第一篇
前言: 都说现在是草根为尊的时代,近年来hadoop及spark技术在国内越来越流行.而且渐渐现成为企业的新宠.在DT时代全面来临之前,能提早接触大数据的技术必然能先人一步.本文作为Hadoop系列 ...
- mysql 数据库优化第一篇(基础)
Mysql数据库优化 1. 优化概述 存储层:存储引擎.字段类型选择.范式设计 设计层:索引.缓存.分区(分表) 架构层:多个mysql服务器设置,读写分离(主从模式) sql语句层:多个sql语句都 ...
- mysql优化----第一篇:综述
一 系统层面 查看CPU和IO状态,确定瓶颈.增 更换设备 二 数据库层面 1 参数优化. 参考文章<mysql性能优化----调整参数>增大数据库内存缓存等设置. 参考 http: ...
- SQL&EF优化第一篇 各种情况下的性能测试之count函数篇
测试环境 mssql 08 +win7 数据 30W条 二〇一六年十月二十九日 09:04:43 结论:1>主键> *>可空列 推测未论证: 根据情况优先选择 顺便提 ...
- 大数据Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- Hadoop核心架构HDFS+MapReduce+Hbase+Hive内部机理详解
转自:http://blog.csdn.net/iamdll/article/details/20998035 分类: 分布式 2014-03-11 10:31 156人阅读 评论(0) 收藏 举报 ...
- Hadoop 系列文章(二) Hadoop配置部署启动HDFS及本地模式运行MapReduce
接着上一篇文章,继续我们 hadoop 的入门案例. 1. 修改 core-site.xml 文件 [bamboo@hadoop-senior hadoop-2.5.0]$ vim etc/hadoo ...
- 第一篇:Hadoop简介
前言 本文大致介绍下Hadoop的一些背景知识,为后面深入学习打下铺垫. 什么是Hadoop Hadoop是一个开源分布式计算平台,它以HDFS文件系统和MapReduce计算框架为核心. 前者能够让 ...
- Mysql优化(出自官方文档) - 第一篇(SQL优化系列)
Mysql优化(出自官方文档) - 第一篇 目录 Mysql优化(出自官方文档) - 第一篇 1 WHERE Clause Optimization 2 Range Optimization Skip ...
随机推荐
- springboot json返回null问题处理
在开发过程中,我们需要统一返回前端json格式的数据,但有些接口的返回值存在 null或者""这种没有意义的字段.以上不仅影响理解,还浪费带宽,这时我们可以统一做一下处理:不返回空 ...
- 如何自定义CSS滚动条的样式?
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由前端林子发表 本文会介绍CSS滚动条选择器,并在demo中展示如何在Webkit内核浏览器和IE浏览器中,自定义一个横向以及一个纵向的 ...
- 经济学人使用Golang构建微服务历程回顾
关键点 经济学人内容分发系统需要更大的灵活性,将内容传递给日益多样化的数字渠道.为了实现这一灵活性目标并保持高水平的性能和可靠性,平台从一个单体结构过渡到微服务体系结构. 用Go编写的服务是新系统的一 ...
- 根据运算符优先级解析SQL规则表达式
1.需求 测试数据库使用Greenplum,生产库使用GBase 普通表:存储客户数据,千万级别,结构如下 stat_date代表日期:user_id代表用户id:serial_number代表手机号 ...
- c# Session写入读取操作
/// <summary> /// 写Session /// </summary> /// <typeparam name="T">Sessio ...
- log4j.appender.file.DatePattern
DailyRollingFileAppender是日志记录软件包Log4J中的一个Appender,它能够按一定的频度滚动日志记录文件. 我们可以按下面的方式配置DailyRollingFileApp ...
- Centos7 firewalld 基本使用
Centos7 的防火墙 firewalld比较常见 简单介绍使用 详细介绍链接推荐: https://blog.csdn.net/buster_zr/article/details/806049 ...
- MVC中使用JQuery方式进行异步请求和使用自带方式进行异步请求
在MCV中使用异步请求可以很很高效地进行前台和后台的数据传递,在这里,笔者为初学者介绍两种在MVC中常用的异步请求处理方式. 在这里,我们通过在一个页面中放置一个按钮来异步获取当前服务器端的系统时间为 ...
- 外边距塌陷 margin collapsing
块的顶部外边距和底部外边距有时被组合(折叠)为单个外边距,其大小是组合到其中的最大外边距, 这种行为称为外边距塌陷(margin collapsing),有的地方翻译为外边距合并. 1.相邻的兄弟姐妹 ...
- Salesforce Live Agent 简介
Live Agent Salesforce 内置了即时聊天功能--Live Agent,可以用来作为客服工具. 本文简单介绍了使用 Live Agent 的步骤,主要包含: 启用 Live Agent ...