大数据存储平台调优之Hadoop优化

大数据存储平台调优之Hadoop优化

在上节搭建完集群、完成Linux系统配置(优化)后以及建好HDFS上的目录后,我们接下来需要对Hadoop集群做一些优化的工作。我们从两个方面来说:一是HDFS存储方面,一是计算方面

 1、 HDFS方面:

1> 存储格式的选择

对于分析类型的业务来说,最好的存储格式自然是列存储,因为数据量巨大,只扫关心的数据列无疑具有很大优势。目前hadoop生态中有两大列存储格式,一个是由Hortonworks和Microsoft开发的ORCFile,另一个是由Cloudera和Twitter开发的Parquet。Parquet是面向分析型业务的列式存储格式,最早由Twitter和Cloudera合作开发,2015年5月升级为Apache顶级项目

 ORCFile是在RCFile的基础之上改造的。RCFile虽然号称列存储,但是只是“按列存储”而已,将数据先划分成row group,然后row group内部按照列进行存储。这其中没有列存储的一些关键特性,而这些特性在以前的列式数据库中早已用到。好在ORCFile已经弥补了这些特性,包括:

块过滤与块统计:每一列按照固定行数或大小进一步切分,对于切分出来的每一个数据单元,预先计算好这些单元的min/max/sum/count/null值,min/max用于在过滤数据的时候直接跳过数据单元,而所有这些统计值则可以在做聚合操作的时候直接采用,而不必解开这个数据单元做进一步的计算。

更高效的编码方式:RCFile中没有标注每一列的类型,事实上当知道数据类型时,可以采取特定的编码方式,本身就能很大程度上进行数据的压缩。常见的针对列存储的编码方式有RLE(大量重复数据),字典(字符串),位图(数字且基数不大)等等

Parquet的设计原理跟ORC类似,不过它有两个特点:

 通用性:相比ORCFile专门给Hive使用而言,Parquet不仅仅是给Impala使用,还可以给其他查询工具使用,如Hive、Pig,进一步还能对接avro/thrift/pb等序列化格式。

基于Dremel思想的嵌套格式存储:关系数据库设计模式中反对存储复杂格式(违反第一范式),但是现在的大数据计算不仅出现了这种需求(半结构化数据),也能够高效的实现存储和查询效率,在语法上也有相应的支持(各种UDF,Hive的lateral view等)。Google Dremel就在实现层面做出了范例,Parquet则完全仿照了Dremel。

         只读取需要的数据,跳过不符合条件的数据,降低I/O

扫描二维码关注公众号,回复: 1214209 查看本文章

         压缩,一般采用snappy压缩

         查询性能较xx提升30倍,存储空间节省70%

 3>大量小文件处理

  因为Namenode把文件系统的元数据放置在内存中,所以文件系统所能容纳的文件数目是由Namenode的内存大小来决定。当文件数到数十亿时,对于当前的硬件水平来说就没法实现了。还有一个问题就是,因为map task的数量splits来决定的,所以用MR处理大量的小文件时,就会产生过多的map task,我们知道在Hadoop中map任务或者reduce任务的都是进程方式启动的,启动进程本身需要花费几秒时间,因此针对小文件的改进策略,有几种方法:

·     利用Har等方式归档小文件,这个方法的原理就是把小文件归档起来管理。这种方法的缺点在于:如果想找回原来的小文件内容,那就必须事先保留原始小文件与归档文件的映射关系

·     既然1个Master有影响,那么能不能来个多Master设计,最新的Hadoop也有这方面的实现,但生产环境上使用这种方法的公司并不多,应慎用

 4>fs.trash.interval

  • 说明: 开启HDFS文件删除自动转移到垃圾箱的选项,值为垃圾箱文件清理过期数据文件的时间,默认值是0,单位是分钟。强烈建议开启此选项,以防错误删除重要文件。

dfs.blocksize

  • 默认值:134217728
  • 说明: HDFS里一个文件块的大小,Hadoop2.7中默认128M。太大会有较少map参与计算,耗时间较长,太小的话需要较多的map个数资源,而且文件太小会浪费namenode内存。建议根据业务数据文件大小进行设置。

dfs.namenode.handler.count

  • 默认值:10
  • 说明:设定 namenode server threads 的数量,这些 threads 會用 RPC 跟其他的 datanodes 沟通。当 datanodes 数量太多时会发現很容易出現 RPC timeout,解決方法是提升网络速度或提高这个值,但要注意的是 thread 数量多也表示 namenode 消耗的内存也随着增加

2> 传输使用AVRO

支持二进制编码、支持JSON编码

         支持压缩

         支持数据排序

         序列化速度快

 二、计算方面的优化

计算方面通常涉及的是YARN和MapReduce的优化,YARN同时支持内存和CPU两种资源的调度,在YARN中,YARN通过分配Container来给每个应用提供处理能力, Container是YARN中处理能力的基本单位,是对内存,CPU等的封装。一个Container的内存是由java heap,jvm overhead和non java memory三部分构成的,如果用户为应用程序设置的内存大小为X GB(-xmxXg),jvm overhead为D GB。则ApplicationMaster为其申请的Container内存大小应为X+D,否则可能会因总内存超出限制被YARN杀死。通常经验是java heap的1.3倍左右是其Container的内存大小
在计算方面,我们还是从硬件资源开始,我们需要注意每台服务器上的内存大小、CPU核数、硬盘数。此外,我们还应该给操作系统预留一部分内存核核数来保证服务器或者其他进程(如HBase)所需的内存和核数,建议大家给服务器预留的内存大小如下:
每个节点的总内存
推荐保留系统内存
推荐保留HBase内存
16 GB
2 GB
2 GB
24 GB
4GB
4GB
48 GB
6 GB
8 GB
64 GB
8 GB
8 GB
72 GB
8 GB
8 GB
96 GB
12 GB
16 GB
128 GB
24 GB
24 GB
256 GB
32 GB
32 GB
512 GB
64 GB
64 GB
接下来我们需要确定每台机器可使用的最大容器个数,使用以下公式:
容器数(containers) = min(2 * CORES,1.8 * DISKS,(可用RAM总数)/ MIN_CONTAINER_SIZE)
MIN_CONTAINER_SIZE是最小容器大小(以RAM为单位)。该值取决于可用RAM的数量 - 在较小的存储器节点中,最小容器大小也应该更小。下表列出了推荐值:
每个节点的总RAM
推荐最小容器大小
小于4 GB
256 MB
在4 GB和8 GB之间
512 MB
介于8 GB和24 GB之间
1024 MB
高于24 GB
2048 MB
最终计算是确定每个容器的RAM量:
每容器可用内存= max(MIN_CONTAINER_SIZE,(可用RAM总数)/容器))
通过这些计算,可以设置YARN和MapReduce配置:
配置文件
配置参数项
配置参数值
yarn-site.xml
yarn.nodemanager.resource.memory-mb
= 容器数 * 每容器可用内存
yarn-site.xml
yarn.scheduler.minimum-allocation-mb
= 每容器可用内存
yarn-site.xml
yarn.scheduler.maximum-allocation-mb
= 容器数 * 每容器可用内存
mapred-site.xml
mapreduce.map.memory.mb
= 每容器可用内存
mapred-site.xml        
mapreduce.reduce.memory.mb
= 2 * 每容器可用内存
mapred-site.xml
mapreduce.map.java.opts
= 0.8  * 每容器可用内存
mapred-site.xml
mapreduce.reduce.java.opts
= 0.8 * 2 * 每容器可用内存
yarn-site.xml (check)
yarn.app.mapreduce.am.resource.mb
= 2 * 每容器可用内存
yarn-site.xml (check)
yarn.app.mapreduce.am.command-opts
= 0.8 * 2 * 每容器可用内存
如果你觉得上述计算起来挺费劲的,hortonworks公司也提供了hdp-configuration-utils.py脚本帮大家计算(这个脚本已经集成在ambari里,改动的时候,ambari会给出可能会影响到的相关参数及值,非常贴心)。

python hdp-configuration-utils.py<options>

参数说明:
Option
Description
-c CORES
The number of cores on each host.
-m MEMORY
The amount of memory on each host in GB.
-d DISKS
The number of disks on each host.
-k HBASE
"True" if HBase is installed, "False" if not.
 举例说明:

pythonhdp-configuration-utils.py -c 32 -m 128 -d 11 -k False

 Using cores=32 memory=128GB disks=11HBase=False

 Profile: cores=32 memory=106496MBreserved=24GB usableMem=104GB disks=11

 Num Container=20

 Container Ram=5120MB

 Used Ram=100GB

 Unused Ram=24GB

 yarn.scheduler.minimum-allocation-mb=5120

 yarn.scheduler.maximum-allocation-mb=102400

 yarn.nodemanager.resource.memory-mb=102400

 mapreduce.map.memory.mb=5120

 mapreduce.map.java.opts=-Xmx4096m

 mapreduce.reduce.memory.mb=5120

 mapreduce.reduce.java.opts=-Xmx4096m

 yarn.app.mapreduce.am.resource.mb=5120

 yarn.app.mapreduce.am.command-opts=-Xmx4096m

 mapreduce.task.io.sort.mb=2048

 需要特别指出的是每个容器将运行JVM以进行映射和减少任务。应将JVM堆大小(java.opts中的-Xmx)设置为低于容器(memory.mb)的值,以使其位于YARN分配的Container内存的边界内, java.opts一般设置为memory.mb的75%左右

举个列子在mapred-site.xml中:

<name>mapreduce.map.memory.mb</name>
<value>4096</value>
那么我们需要
<name>mapreduce.map.java.opts</name>
<value>-Xmx3072m</value>

猜你喜欢

转载自blog.csdn.net/odailidong/article/details/79575613