主要集中在两个方面:一是计算性能方面的优化;二是I/O操作方面的优化
1. 任务调度
所有的任务能公平地分享系统资源
2. 数据预处理与InputSplit的大小
合理地设置block块大小 dfs.block.size 默认值是67108864 (64MB)。对于很多情况来说,134217728 (128MB)更加合适
可以使用这个命令去修改已存在文件的block size: hadoop distcp -Ddfs.block.size=$[256*1024*1024] /path/to/inputdata /path/to/inputdata-with/largeblocks。
在执行完这个命令后,你就可以删除原始的输入文件了(/path/to/inputdata)。
3. Map和Reduce任务的数量
mapred.tasktracker.map.tasks.maximum 以及 mapred.tasktracker.reduce.tasks.maximum。这两个参数设置了一台服务器上最多能同时运行的map和reduce数
设置MapReduce任务的Map数量主要参考的是Map的运行时间,设置Reduce任务的数量就只需要参考任务槽的设置即可。
如果你发现reduce在33%时,map正好提早一点点到100%,那么这将是最佳的配比,
因为reduce是在33%的时候完成了copy阶段,也就是说,map需要再reduce到达33%之前完成所有的map任务,准备好数据。
一般来说,Reduce任务的数量应该是Reduce任务槽的0.95倍或是1.75倍,这是基于不同的考虑来决定的
当Reduce任务的数量是任务槽的0.95倍时,如果一个Reduce任务失败,Hadoop可以很快地找到一台空闲的机器重新执行这个任务。
当Reduce任务的数量是任务槽的1.75倍时,执行速度快的机器可以获得更多的Reduce任务,因此可以使负载更加均衡,以提高任务的处理速度。
4. Combine函数
在WordCount程序中,可以指定Reduce类为combine函数,具体如下:
job.setCombinerClass(Reduce.class);
5. 压缩
对Map的输出和最终的输出结果进行压缩
6. 自定义comparator使用最合适和简洁的Writable类型大部分的输出值很小的时候使用IntWritable 或 LongWritable对象。
自定义comparator来实现数据的二进制比较,这样可以省去数据序列化和反序列化的时间,提高程序的运行效率
使用StringBuffer.append来连接字符串
7、DFS和MapReduce中使用的存储mount被设置了noatime选项。这项如果设置就不会启动对磁盘访问时间的记录,会显著提高IO的性能。
8. 避免在TaskTracker和DataNode的机器上执行RAID和LVM操作,这通常会降低性能
9. 在这两个参数mapred.local.dir和dfs.data.dir 配置的值应当是分布在各个磁盘上目录,这样可以充分利用节点的IO读写能力。
10. 使用像Ganglia这样的工具监控并绘出swap和网络的利用率图。如果你从监控的图看出机器正在使用swap内存,那么减少mapred.child.java.opts属性所表示的内存分配。
11、内存
io.sort.mb和mapred.child.java.opts
一般设置JVM的最大可用内存量为mb设置的内存量的两倍
如果一个map的结果数据量为600M,那么如果你设置的mb*io.sort.spill.percent.=200M,那么将进行3次spill进入硬盘,然后map完成后再将数据从硬盘上取出进行copy。
所以,这个mb设置如果是600M的话,那么就不需要进行这次硬盘访问了,节省了很多时间。但是最大的问题是内存耗费很大。
如果mb是600M,那么jvm.opts将需要设置为1G以上,那么,按照上例,你同时启动16个map和8个reduce 的话,那么你的内存至少应该有24G。
12、io.file.buffer.size都被用来设置缓存的大小
io.file.buffer.size默认值是4KB,一般情况下,可以设置为64KB(65536byte)
13、配置调度器
FIFO
Hadoop 中默认的调度器,它先按照作业的优先级高低,再按照到达时间的先后选 择被执行的作业
公平调度器
为任务分配资源的方法,其目的是随着时间的推移,让提交的作业获取等量的集 群共享资源,让用户公平地共享集群。具体做法是:当集群上只有一个任务在运行 时,它将使用整个集群,当有其他作业提交时,系统会将TaskTracker节点空间的时 间片分配给这些新的作业,并保证每个任务都得到大概等量的CPU时间。
容量调度器
支持多个队列,每个队列可配置一定的资源量,每个队列采用 FIFO 调度策略,为 了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交 的作业所 占资源量进行限定。调度时,首先按以下策略选择一个合适队列:计算每个队列中 正在运行的任务数与其应该分得的计算资源之间的比值,选择一个该比值 最小的队 列;然后按以下策略选择该队列中一个作业:按照作业优先级和提交时间顺序选择 ,同时考虑用户资源量限制和内存限制。但是不可剥夺式
配置公平调度器
1.修改mapred-stie.xml 加入如下内容
<property>
<name>mapred.jobtracker.taskScheduler</name>
<value>org.apache.hadoop.mapred.FairScheduler</value>
</property>
<property>
<name>mapred.fairscheduler.allocation.file</name>
<value>/opt/hadoop/conf/allocations.xml</value>
</property>
<property>
<name>mapred.fairscheduler.poolnameproperty</name>
<value>pool.name</value>
</property>
2 . 在 Hadoop conf 下创建
allocations.xml
内容为
<?xml version="1.0"?>
<alloctions>
</alloctions>
样例:
<pool name="sample_pool">
<minMaps>5</minMaps>
<minReduces>5</minReduces>
<weight>2.0</weight>
</pool>
<user name="sample_user">
<maxRunningJobs>6</maxRunningJobs>
</user>
<userMaxJobsDefault>3</userMaxJobsDefault>
3. 重启 JobTracker
4. 访问 http://jobTracker:50030/scheduler , 查看 FariScheduler 的 UI
5 . 提交任务测试
1. 任务调度
所有的任务能公平地分享系统资源
2. 数据预处理与InputSplit的大小
合理地设置block块大小 dfs.block.size 默认值是67108864 (64MB)。对于很多情况来说,134217728 (128MB)更加合适
可以使用这个命令去修改已存在文件的block size: hadoop distcp -Ddfs.block.size=$[256*1024*1024] /path/to/inputdata /path/to/inputdata-with/largeblocks。
在执行完这个命令后,你就可以删除原始的输入文件了(/path/to/inputdata)。
3. Map和Reduce任务的数量
mapred.tasktracker.map.tasks.maximum 以及 mapred.tasktracker.reduce.tasks.maximum。这两个参数设置了一台服务器上最多能同时运行的map和reduce数
设置MapReduce任务的Map数量主要参考的是Map的运行时间,设置Reduce任务的数量就只需要参考任务槽的设置即可。
如果你发现reduce在33%时,map正好提早一点点到100%,那么这将是最佳的配比,
因为reduce是在33%的时候完成了copy阶段,也就是说,map需要再reduce到达33%之前完成所有的map任务,准备好数据。
一般来说,Reduce任务的数量应该是Reduce任务槽的0.95倍或是1.75倍,这是基于不同的考虑来决定的
当Reduce任务的数量是任务槽的0.95倍时,如果一个Reduce任务失败,Hadoop可以很快地找到一台空闲的机器重新执行这个任务。
当Reduce任务的数量是任务槽的1.75倍时,执行速度快的机器可以获得更多的Reduce任务,因此可以使负载更加均衡,以提高任务的处理速度。
4. Combine函数
在WordCount程序中,可以指定Reduce类为combine函数,具体如下:
job.setCombinerClass(Reduce.class);
5. 压缩
对Map的输出和最终的输出结果进行压缩
6. 自定义comparator使用最合适和简洁的Writable类型大部分的输出值很小的时候使用IntWritable 或 LongWritable对象。
自定义comparator来实现数据的二进制比较,这样可以省去数据序列化和反序列化的时间,提高程序的运行效率
使用StringBuffer.append来连接字符串
7、DFS和MapReduce中使用的存储mount被设置了noatime选项。这项如果设置就不会启动对磁盘访问时间的记录,会显著提高IO的性能。
8. 避免在TaskTracker和DataNode的机器上执行RAID和LVM操作,这通常会降低性能
9. 在这两个参数mapred.local.dir和dfs.data.dir 配置的值应当是分布在各个磁盘上目录,这样可以充分利用节点的IO读写能力。
10. 使用像Ganglia这样的工具监控并绘出swap和网络的利用率图。如果你从监控的图看出机器正在使用swap内存,那么减少mapred.child.java.opts属性所表示的内存分配。
11、内存
io.sort.mb和mapred.child.java.opts
一般设置JVM的最大可用内存量为mb设置的内存量的两倍
如果一个map的结果数据量为600M,那么如果你设置的mb*io.sort.spill.percent.=200M,那么将进行3次spill进入硬盘,然后map完成后再将数据从硬盘上取出进行copy。
所以,这个mb设置如果是600M的话,那么就不需要进行这次硬盘访问了,节省了很多时间。但是最大的问题是内存耗费很大。
如果mb是600M,那么jvm.opts将需要设置为1G以上,那么,按照上例,你同时启动16个map和8个reduce 的话,那么你的内存至少应该有24G。
12、io.file.buffer.size都被用来设置缓存的大小
io.file.buffer.size默认值是4KB,一般情况下,可以设置为64KB(65536byte)
13、配置调度器
FIFO
Hadoop 中默认的调度器,它先按照作业的优先级高低,再按照到达时间的先后选 择被执行的作业
公平调度器
为任务分配资源的方法,其目的是随着时间的推移,让提交的作业获取等量的集 群共享资源,让用户公平地共享集群。具体做法是:当集群上只有一个任务在运行 时,它将使用整个集群,当有其他作业提交时,系统会将TaskTracker节点空间的时 间片分配给这些新的作业,并保证每个任务都得到大概等量的CPU时间。
容量调度器
支持多个队列,每个队列可配置一定的资源量,每个队列采用 FIFO 调度策略,为 了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交 的作业所 占资源量进行限定。调度时,首先按以下策略选择一个合适队列:计算每个队列中 正在运行的任务数与其应该分得的计算资源之间的比值,选择一个该比值 最小的队 列;然后按以下策略选择该队列中一个作业:按照作业优先级和提交时间顺序选择 ,同时考虑用户资源量限制和内存限制。但是不可剥夺式
配置公平调度器
1.修改mapred-stie.xml 加入如下内容
<property>
<name>mapred.jobtracker.taskScheduler</name>
<value>org.apache.hadoop.mapred.FairScheduler</value>
</property>
<property>
<name>mapred.fairscheduler.allocation.file</name>
<value>/opt/hadoop/conf/allocations.xml</value>
</property>
<property>
<name>mapred.fairscheduler.poolnameproperty</name>
<value>pool.name</value>
</property>
2 . 在 Hadoop conf 下创建
allocations.xml
内容为
<?xml version="1.0"?>
<alloctions>
</alloctions>
样例:
<pool name="sample_pool">
<minMaps>5</minMaps>
<minReduces>5</minReduces>
<weight>2.0</weight>
</pool>
<user name="sample_user">
<maxRunningJobs>6</maxRunningJobs>
</user>
<userMaxJobsDefault>3</userMaxJobsDefault>
3. 重启 JobTracker
4. 访问 http://jobTracker:50030/scheduler , 查看 FariScheduler 的 UI
5 . 提交任务测试