一、硬件因素
Ø 内存
Hbase对内存有特别的嗜好,因为内存越大,regionserver接受客户端传递来的数据时可以在内存中做缓存(memstore)以及排序,分配给region等操作的限度更大,相当于利用内存作为缓冲池,组织好hbase需要的数据之后再统一写的顺序写硬盘。
*推荐32GB内存
Ø CPU
CPU参与边界计算以及数据排序等操作,当内存非常大时,CPU对内存中数据的组织,排序,边界计算等可能成为瓶颈。
*推荐8核cpu,同时可满足mapreduce的需求
Ø 网络I/O
以目前的集群状况来看(10节点小集群),网络I/O没有达到瓶颈。
*推荐用千兆双网卡绑定,万兆交换机,最大限度提高网络吞吐率。
Ø 硬盘
在测试入库时需要关注硬盘的iowait情况,虽然内存往硬盘上flush数据时顺序写操作,但在某些情况下会出现硬盘iowait高,造成瓶颈。另外需要关闭swap来保证硬盘不会被频繁的调入swap使用。在配置hdfs的时候不要对多块盘坐raid,而是要直接挂载到某些目录下。
*推荐使用500GB的SATA/SAS盘,7200转,节点8块盘
二、Hbase配置参数
Ø hbase.hregion.max.filesize
这个参数是单个region的最大字节数,当region中的数据达到这个值之后就会平均分裂成2个region
Ø hbase.hregion.memstore.flush.size
这个参数是每次内存能缓存的数据最大字节数,当memstore中缓存的数据达到这个值,hbase就将数据flush到硬盘上
Ø hbase.regionserver.handler.count
这个参数决定了每个regionserver能够开启的最大handler数量,即接受客户端请求的句柄数,这个数量越大能接受的客户端以及线程数越多
Ø HBASE_HEAPSIZE
这个参数决定了hbase最多能调用物理机的内存大小,尽量配置大一些
hbase.hregion.max.filesize和hbase.hregion.memstore.flush.size参数的配置有讲究。目前有2种设计思路:
1、 建表时预划分region,对数据有清楚的把握(数据量、rowkey分布),能够进行将region分好,而无需启用hbase的自split策略,这种方式能够提高集群稳定性,缺点是操作上较困难。在此情况下hbase.hregion.max.filesize设置为1TB或更大值
2、 数据无法估量,采用hbase自身split机制。灵活性高,易操作,缺点是存在不稳定风险。在此情况下将hbase.hregion.max.filesize设置为1GB-2GB较合理
3、 无论上述哪种情况,hbase.hregion.memstore.flush.size在200MB左右是经过多次测试后一个较理想值
二、Hadoop配置参数
hbase是基于hadoop构建的,要调优hbase入库性能必然少不了调优hdfs。这里发现了几个比较有用的参数
dfs.replication.interval:默认为3秒,就是hadoop检查备份的时间间隔,这个时间稍微设长一点可以避免hdfs频繁备份,提高hdfs吞吐效率
dfs.datanode.handler.count:datanode的handler,增加datanode的handler数
dfs.namenode.handler.count:namenode的handler数。
三、系统架构因素
Ø Client端
入库时对client的数量和开启的线程数量有要求,对client机器性能也有一定的要求,因为实际测试的时候发现client端开启50个线程后机器性能占用比较满。
Ø Regionserver端
Regionserver端越多,能同时接受的请求就越多,入库速度就越快。
四、配套软件
操作系统:64位centOS
JDK:sun64位jdk
Hadoop:0.20.2-cdh3版
Hbase:0.90.3-cdh3版
五、hbase表设计因素
hbase表如果设计成多列族会比单列族的时候入库速度慢。因为多列族的时候hbase做memstore的flush时对一个store文件的flush会同时触发其他store的flush,这个可能是hbase的一个bug,目前来说设计表的时候不要将列族设计到3个以上。
五、入库程序设计因素
入库程序的设计上最好在创建Htable的时候就设置好region的数量,start_key和end_key,这样就能够使程序开始运行的时候向每个regionserver传递请求。另外start_key和end_key的设计可以让数据较紧凑的平均分发到各个region上。
入库程序不要手动做table.flushcommit(),而是使用hbase自带的memstore->硬盘的写入机制,只需要table.put即可。然后设置table的自动提交功能为false(如果为true的话每次调用table.put的时候都会触发一次操作)。
数据入库时只对自动提交选项设为false,而不对writebuffersize做设置效果会比较好,看了hbase的代码不设置的话默认值是2MB,writebuffersize的设置不能太大,也不能太小,实际测试中2-5MB之间比较合理
入库程序设计要开尽可能多的线程,推荐20-25线程,在多个机器上运行,同时读取本地文件,在并发数量大的情况下入库效率会得到较大提升。
BlukLoad入库:除了client方式之外,可以通过mr来生成hfile,之后将hfile直接导入hbase的方式入库。目前以这种方式进行大文件批量入库是最为理想的方法。最近会写篇文章专门谈一下这块。
六、最新的测试情况
目前集群含有12个节点,9台client,regionserver的内存设置为13000M,修改region的最大大小为400G(目的是为了不做分裂);提前划分region 200个;region的flush大小为4G,client的writebuffersize为64MB,每个开20线程。入库速度能达到30MB/s,hbase的request到10w。单列族的表入库速度能达到20w的request。50MB/s
2011年10月9日:
采用单列族,单列的方式使hbase入库速度达到最快值,大约8MB/s的单节点入库速度,总集群速度达到72MB/s,request峰值80W/s。(前提是提升了内存到32GB)。
最新碰到的问题是1TB数据入库的时候,每次触发memstore flush有三个现象
1)flush的文件size很小:我考察了两个触发flush的条件,一个是hbase.regionserver.global.memstore.upperLimit,一个是hbase.hregion.memstore.flush.size,都不是这两个原因。
2)耗时很高:可能是磁盘IO性能不够
3)波动较大:磁盘IO跟不上接收速度
2011年11月28日:
目前关闭wal,入库速度终于突破100W/s,取得了阶段性的成果。
2012年2月25日:
参与上海数据中心测试,在较好硬件支持下,集群的入库速度达到200W/s,并且持续稳定运行。入库速度达到实测中最理想情况,每台机器的硬件平均利用率指标在70-80%左右。
七、写在末尾的一段话
本篇文章的撰写背景是为了解决在大规模数据入库情况下入库性能瓶颈,适用场景为:TB级别数据,10台机器。
这里要感谢淘宝的众位大哥,很欣赏淘宝在技术上开放的心态,通过线上线下交流、技术博客学到不少。也感谢公司,能给我个人一个宽松的环境,做我自己喜欢的事情。mark一下国防科大的哥们,我是锐安科技的hbase研发。
我在2011年中hbase入库优化工作告一段落,所以如果不是有大的谬误,不会再更新本博文。2012年,开启新的征程!