一、通用优化1.1、NameNode 的元数据备份使用 SSD1.2、定时备份 NameNode 上的元数据1.3、为 NameNode 指定多个元数据目录1.4、设置 dfs.namenode.name.dir.restore 为 true1.5、NameNode 节点必须配置为 Raid1(镜像盘)结构1.6、补充:什么是Raid0、Raid0+1、Raid1、Raid51.7、保持 NameNode 日志目录有足够的空间,这些日志有助于帮助你发现问题1.8、因为 Hadoop 是 IO 密集型框架,所以尽量提升存储的速度和吞吐量(类似位宽)二、Linux 优化2.1、开启文件系统的预读缓存可以提高读取速度2.2、关闭进程睡眠池2.3 修改系统能够打开的文件句柄数2.4、开启集群的时间同步 NTP,请参看一下链接2.5、更新系统补丁(尖叫提示:更新补丁前,请先测试新版本补丁对集群节点的兼容性)三、HDFS 优化(hdfs-site.xml)3.1、保证 RPC 调用会有较多的线程数3.2、副本数的调整3.3.、文件块大小的调整四、MapReduce 优化(mapred-site.xml)4.1、Job 任务服务线程数调整4.2、Http 服务器工作线程数4.3、文件排序合并优化4.5、设置任务并发4.6、MR 输出数据的压缩4.7、优化 Mapper 和 Reducer 的个数五、HBase 优化5.1、在 HDFS 的文件中追加内容5.2、优化 DataNode 允许的最大文件打开数5.3、优化延迟高的数据操作的等待时间5.4、优化数据的写入效率5.5、优化 DataNode 存储5.6、设置 RPC 监听数量5.7、优化 HStore 文件大小5.8、优化 hbase 客户端缓存5.9、指定 scan.next 扫描 HBase 所获取的行数六、内存优化七、JVM 优化7.1、并行 GC7.2、同时处理垃圾回收的线程数7.3、禁用手动 GC八、Zookeeper 优化8.1、优化 Zookeeper 会话超时时间
一、通用优化
1.1、NameNode 的元数据备份使用 SSD
1.2、定时备份 NameNode 上的元数据
建议每小时或者每天备份,如果数据极其重要,可以5~10分钟备份一次。备份可以通过定时任务复制元数据目录即可。
1.3、为 NameNode 指定多个元数据目录
使用 dfs.name.dir 或者 dfs.namenode.name.dir 指定。一个指定本地磁盘,一个指定网络磁盘。这样可以提供元数据的冗余和健壮性,以免发生故障。
1.4、设置 dfs.namenode.name.dir.restore 为 true
即允许尝试恢复之前失败的 dfs.namenode.name.dir 目录,在创建 checkpoint 时做此尝试,如果设置了多个磁盘,建议允许。
1.5、NameNode 节点必须配置为 Raid1(镜像盘)结构
1.6、补充:什么是Raid0、Raid0+1、Raid1、Raid5
Standalone:最普遍的单磁盘储存方式。
Cluster:集群储存是通过将数据分布到集群中各节点的存储方式,提供单一的使用接口与界面,使用户可以方便地对所有数据进行统一使用与管理。
Hot swap:用户可以再不关闭系统,不切断电源的情况下取出和更换硬盘,提高系统的恢复能力、拓展性和灵活性。
Raid0:是所有 raid 中存储性能最强的阵列形式
。其工作原理就是在多个磁盘上分散存取连续的数据,这样,当需要存取数据是多个磁盘可以并排执行,每个磁盘执行属于它自己的那部分数据请求,显著提高磁盘整体存取性能。但是不具备容错能力,适用于低成本、低可靠性的台式系统。
Raid1:又称镜像盘,把一个磁盘的数据镜像到另一个磁盘上,采用镜像容错来提高可靠性,具有 raid 中最高的数据冗余能力
。存数据时会将数据同时写入镜像盘内,读取数据则只从工作盘读出。发生故障时,系统将从镜像盘读取数据,然后再恢复工作盘正确数据。这种阵列方式可靠性极高,但是其容量会减去一半。广泛用于数据要求极严的应用场合,如商业金融、档案管理等领域。只允许一个硬盘出故障。
Raid0+1:将 Raid0 和 Raid1 技术结合在一起,兼顾两者的优势。在数据得到保障的同时,还能提供较强的存储性能。不过至少要求4个或以上的硬盘,但也只允许一个磁盘出错。是一种三高技术
。
Raid5:Raid5 可以看成是 Raid0+1 的低成本方案
。采用循环偶校验独立存取的阵列方式。将数据和相对应的奇偶校验信息分布存储到组成 Raid5 的各个磁盘上。当其中一个磁盘数据发生损坏后,利用剩下的磁盘和相应的奇偶校验信息重新恢复/生成丢失的数据而不影响数据的可用性。至少需要3个或以上的硬盘。适用于大数据量的操作。成本稍高、储存新强、可靠性强的阵列方式。
Raid还有其他方式,请自行查阅。
1.7、保持 NameNode 日志目录有足够的空间,这些日志有助于帮助你发现问题
1.8、因为 Hadoop 是 IO 密集型框架,所以尽量提升存储的速度和吞吐量(类似位宽)
二、Linux 优化
2.1、开启文件系统的预读缓存可以提高读取速度
$ sudo blockdev --setra 32768 /dev/sda
(尖叫提示:ra 是 readahead 的缩写)
2.2、关闭进程睡眠池
$ sudo sysctl -w vm.swappiness=0
2.3 修改系统能够打开的文件句柄数
即调整 ulimit 上限,默认值为比较小的数字(CentOS 6.8 默认是 1024)。做高并发服务器或者像聊天这种长连接服务时,需要修改系统能够打开的文件句柄数。否则会出现 too many open files 的错误。socket 句柄和文件句柄是相同的,像聊天这种长链接服务,此时 too many open files 指的就是 socket 句柄数超出了系统的限制。
$ ulimit -n 查看允许最大进程数
$ ulimit -u 查看进程允许打开最大文件数
单进程文件句柄限制
句柄数限制又分为系统总限制
和单进程限制
。使用命令 ulimit -n 可以看到系统对于单个进程的限制,即 open files。执行命令 ulimit -a 如下:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7334
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 1024
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
如果 open files 1024 表示我当前登录的用户(atguigu),每个进程可以打开 1024 个句柄,当然总和不能超过 file-max 限制。
如果 open files 65535 表示我当前登录的用户(root),每个进程可以打开 65535 个句柄,当然总和不能超过 file-max 限制。
修改 open files 的值,有两种方法,临时的和永久的。
临时修改 open files
ulimit -HSn 1000 将 open-files 修改为 1000,退出当前 shell 后即失效。H 和 S 选项表示硬限制和软限制,下面有解释,省略的话表示同时修改。
永久修改 open files
若希望永久生效的话就得修改配置文件,/etc/security/limits.conf,修改后需要重启系统,该文件内容为:
$ sudo vim /etc/security/limits.conf 修改单个进程打开文件数限制
在末尾添加以下内容:
* soft nofile 1024000
* hard nofile 1024000
hive - nofile 1024000
hive - nproc 1024000
第一列:表示对哪些用户进程进行限制,* 表示所有用户。
第二列:
soft:表示软限制,当进程打开的句柄数超过该限制后,只是进行警告。
hard:表示硬限制,进程最多打开这么多句柄。
第三列:nofile 表示进程能够打开的最大文件数,nproc 表示允许最大进程数(其他配置值可以参考文件中的注释,与 ulimit -a 列出的值一一对应)。
第四列:是具体的值,这个值也是有上限的,这个上限的值设置在 /proc/sys/fs/nr_open,默认值为 1048576,完全够用了。
修改后需要重启系统生效。
nr_open 表示一个进程最多能分配的文件句柄数
cat /proc/sys/fs/nr_open
1048576
系统总打开文件句柄限制
上面的 open files 是对单个进程的限制,属于线程级别的。系统级的限制在这个文件中 /proc/sys/fs/file-max
cat /proc/sys/fs/file-max
185890
file-max 指定了系统范围内所有进程可以打开的文件句柄限制。
同样,修改上面那个文件也是临时生效的,重启后会失效。如果要永久生效,则要修改这个文件, /etc/sysctl.conf
fs.file-max = 185890
如果没有这一项,则新加这一项就行。运行 sysctl -p 或重启后才能生效。
lsof -p 进程pid 查看单个进程打开的文件句柄
lsof -p 4512
/proc/sys/fs/file-nr 记录当前系统打开的句柄数
cat /proc/sys/fs/file-nr
2240 0 185890
第一列:表示已打开的句柄数
第二列:表示已分配但是未使用的句柄数
第三列:表示系统总的句柄数,即 file-max
总结
所有进程能够打开的文件句柄总数不能超过 file-max
单个进程打开的句柄数不能超过nofile soft limit
nofile soft limit 的设置不能超过nofile hard limit
nofile hard limit 的设置不能超过 no_open
no_open 的设置不能超过 file-max
修改用户打开进程数限制
$ sudo vim /etc/security/limits.d/90-nproc.conf 修改用户打开进程数限制
修改为:
* soft nproc 40960
root soft nproc unlimited
修改后需要重启系统生效。
2.4、开启集群的时间同步 NTP,请参看一下链接
https://www.cnblogs.com/chenmingjun/p/10545638.html
2.5、更新系统补丁(尖叫提示:更新补丁前,请先测试新版本补丁对集群节点的兼容性)
三、HDFS 优化(hdfs-site.xml)
3.1、保证 RPC 调用会有较多的线程数
属性:dfs.namenode.handler.count**
解释:该属性是 NameNode 服务默认线程数,的默认值是 10,根据机器的可用内存可以调整为 50~100 。
属性:dfs.datanode.handler.count
解释:该属性默认值为 10,是 DataNode 的处理线程数,如果 HDFS 客户端程序读写请求比较多,可以调高到 15~20,设置的值越大,内存消耗越多,不要调整的过高,一般业务中,5~10 即可。
3.2、副本数的调整
属性:dfs.replication
解释:如果数据量巨大,且不是非常之重要,可以调整为 2~3,如果数据非常之重要,可以调整为 3~5。
3.3.、文件块大小的调整
属性:dfs.blocksize
解释:块大小定义,该属性应该根据存储的大量的单个文件大小来设置,如果大量的单个文件都小于 100M,建议设置成 64M 块大小,对于大于 100M 或者达到 GB 的这种情况,建议设置成 256M,一般设置范围波动在 64M~256M 之间。
四、MapReduce 优化(mapred-site.xml)
4.1、Job 任务服务线程数调整
属性:mapreduce.jobtracker.handler.count
解释:该属性是 Job 任务线程数,默认值是 10,根据机器的可用内存可以调整为 50~100。
4.2、Http 服务器工作线程数
属性:mapreduce.tasktracker.http.threads
解释:定义 HTTP 服务器工作线程数,默认值为 40,对于大集群可以调整到 80~100。
4.3、文件排序合并优化
属性:mapreduce.task.io.sort.factor
解释:文件排序时同时合并的数据流的数量,这也定义了同时打开文件的个数,默认值为 10,如果调高该参数,可以明显减少磁盘 IO,即减少文件读取的次数。
4.5、设置任务并发
属性:mapreduce.map.speculative
解释:该属性可以设置任务是否可以并发执行,如果任务多而小,该属性设置为 true 可以明显加快任务执行效率,但是对于延迟非常高的任务,建议改为 false,这就类似于迅雷下载。
4.6、MR 输出数据的压缩
属性:mapreduce.map.output.compress、mapreduce.output.fileoutputformat.compress
解释:对于大集群而言,建议设置 Map-Reduce 的输出为压缩的数据,而对于小集群,则不需要。
4.7、优化 Mapper 和 Reducer 的个数
属性:
mapreduce.tasktracker.map.tasks.maximum
mapreduce.tasktracker.reduce.tasks.maximum
解释:
以上两个属性分别为一个单独的 Job 任务可以同时运行的 Map 和 Reduce 的数量。
设置上面两个参数时,需要考虑 CPU 核数、磁盘和内存容量。假设一个 8 核的 CPU,业务内容非常消耗 CPU,那么可以设置 map 数量为 4,如果该业务不是特别消耗 CPU 类型的,那么可以设置 map 数量为 40,reduce 数量为 20。这些参数的值修改完成之后,一定要观察是否有较长等待的任务,如果有的话,可以减少数量以加快任务执行,如果设置一个很大的值,会引起大量的上下文切换,以及内存与磁盘之间的数据交换,这里没有标准的配置数值,需要根据业务和硬件配置以及经验来做出选择。
在同一时刻,不要同时运行太多的 MapReduce,这样会消耗过多的内存,任务会执行的非常缓慢,我们需要根据 CPU 核数,内存容量设置一个 MR 任务并发的最大值,使固定数据量的任务完全加载到内存中,避免频繁的内存和磁盘数据交换,从而降低磁盘 IO,提高性能。
大概配比:
CPU CORE | MEM(GB) | Map | Reduce |
---|---|---|---|
1 | 1 | 1 | 1 |
1 | 5 | 1 | 1 |
4 | 5 | 1~4 | 2 |
16 | 32 | 16 | 8 |
16 | 64 | 16 | 8 |
24 | 64 | 24 | 12 |
24 | 128 | 24 | 12 |
大概估算公式:
map = 2 + ⅔cpu_core
reduce = 2 + ⅓cpu_core
五、HBase 优化
5.1、在 HDFS 的文件中追加内容
不是不允许追加内容么?没错,请看背景故事:
属性:dfs.support.append
文件:hdfs-site.xml、hbase-site.xml
解释:开启 HDFS 追加同步,可以优秀的配合 HBase 的数据同步和持久化。默认值为 true。
5.2、优化 DataNode 允许的最大文件打开数
属性:dfs.datanode.max.transfer.threads
文件:hdfs-site.xml
解释:HBase 一般都会同一时间操作大量的文件,根据集群的数量和规模以及数据动作,设置为 4096 或者更高。默认值:4096。
5.3、优化延迟高的数据操作的等待时间
属性:dfs.image.transfer.timeout
文件:hdfs-site.xml
解释:如果对于某一次数据操作来讲,延迟非常高,socket 需要等待更长的时间,建议把该值设置为更大的值(默认 60000 毫秒),以确保 socket 不会被 timeout 掉。
5.4、优化数据的写入效率
属性:
mapreduce.map.output.compress
mapreduce.map.output.compress.codec
文件:mapred-site.xml
解释:开启这两个数据可以大大提高文件的写入效率,减少写入时间。第一个属性值修改为 true,第二个属性值修改为:org.apache.hadoop.io.compress.GzipCodec。
5.5、优化 DataNode 存储
属性:dfs.datanode.failed.volumes.tolerated
文件:hdfs-site.xml
解释:默认为 0,意思是当 DataNode 中有一个磁盘出现故障,则会认为该 DataNode shutdown 了。如果修改为 1,则一个磁盘出现故障时,数据会被复制到其他正常的 DataNode 上,当前的 DataNode 继续工作。
5.6、设置 RPC 监听数量
属性:hbase.regionserver.handler.count
文件:hbase-site.xml
解释:默认值为 30,用于指定 RPC 监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
5.7、优化 HStore 文件大小
属性:hbase.hregion.max.filesize
文件:hbase-site.xml
解释:默认值 10737418240(10GB),如果需要运行 HBase 的 MR 任务,可以减小此值,因为一个 region 对应一个 map 任务,如果单个 region 过大,会导致 map 任务执行时间过长。该值的意思就是,如果 HFile 的大小达到这个数值,则这个 region 会被切分为两个 Hfile。
5.8、优化 hbase 客户端缓存
属性:hbase.client.write.buffer
文件:hbase-site.xml
解释:用于指定 HBase 客户端缓存,增大该值可以减少 RPC 调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少 RPC 次数的目的。
5.9、指定 scan.next 扫描 HBase 所获取的行数
属性:hbase.client.scanner.caching
文件:hbase-site.xml
解释:用于指定 scan.next 方法获取的默认行数,值越大,消耗内存越大。
六、内存优化
HBase 操作过程中需要大量的内存开销,毕竟 Table 是可以缓存在内存中的,一般会分配整个可用内存的 70% 给 HBase 的 Java 堆。但是不建议分配非常大的堆内存,因为 GC 过程持续太久会导致 RegionServer 处于长期不可用状态,一般 16~48G 内存就可以了,如果因为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死。
七、JVM 优化
涉及文件:hbase-env.sh
7.1、并行 GC
参数:-XX:+UseParallelGC
解释:开启并行GC。
7.2、同时处理垃圾回收的线程数
参数:-XX:ParallelGCThreads=cpu_core – 1
解释:该属性设置了同时处理垃圾回收的线程数。
7.3、禁用手动 GC
参数:-XX:DisableExplicitGC
解释:防止开发人员手动调用 GC。
八、Zookeeper 优化
8.1、优化 Zookeeper 会话超时时间
参数:zookeeper.session.timeout
文件:hbase-site.xml
解释:In hbase-site.xml, set zookeeper.session.timeout to 30 seconds or less to bound failure detection (20-30 seconds is a good start) 该值会直接关系到 master 发现服务器宕机的最大周期,默认值为 30 秒,如果该值过小,会在 HBase 在写入大量数据发生而 GC 时,导致 RegionServer 短暂的不可用,从而没有向 ZK 发送心跳包,最终导致认为从节点 shutdown。一般 20 台左右的集群需要配置 5 台 zookeeper。
注意:不同的 HBase 版本,它的 zookeeper 会话超时时间默认是不一样的!