Hadoop2.7.1+Hbase1.1.2集群环境搭建(七)hbase 性能优化
(1)hadoop2.7.1源码编译 http://zilongzilong.iteye.com/blog/2246856
(2)hadoop2.7.1安装准备 http://zilongzilong.iteye.com/blog/2253544
(3)hadoop2.7.1安装 http://zilongzilong.iteye.com/blog/2245547
(4)hbase安装准备 http://zilongzilong.iteye.com/blog/2254451
(5)hbase安装 http://zilongzilong.iteye.com/blog/2254460
(6)snappy安装 http://zilongzilong.iteye.com/blog/2254487
(7)hbase性能优化 http://zilongzilong.iteye.com/blog/2282670
(8)雅虎YCSBC测试hbase性能测试 http://zilongzilong.iteye.com/blog/2248863
(9)spring-hadoop实战 http://zilongzilong.iteye.com/blog/2254491
1.前言
使用hbase有一段时间了,从最开始对hbase读写性能的怀疑,到最后对hbase读写性能的肯定,经历了一个漫长的过程,在此,对hbase相关性能优化写一点个人的总结。
2.官方关于性能优化(最权威)
所有关于技术类的文档,一般官网会有个优化建议,怎么去找呢,一般文档中搜索“Performance Tuning”,意思为性能优化,即可查到。
官方文档其实写的很全面,但点到即止,主要从操作系统、网络、Java、HBase 配置、ZooKeeper、Schema 设计阐述了相关性能优化建议,这里只是贴出文档地址,我在这里不做过多讲解。
2.1 性能优化英文版https://hbase.apache.org/0.94/book.html#performance
2.2 性能优化中文版http://abloz.com/hbase/book.html#performance
3.性能优化关键点
3.1 内存
3.1.1 hbase.regionserver.handler.count
这个参数的本质是设置一个RegsionServer可以同时处理多少请求。 如果定的太高,吞吐量反而会降低;如果定的太低,请求会被阻塞,得不到响应。你可以打开RPC-level日志读Log,来决定对于你的集群什么值是合适的。(请求队列也是会消耗内存的)。我的配置如下:
<property> <name>hbase.regionserver.handler.count</name> <value>300</value> <description>Count of RPC Listener instances spun up on RegionServers.Same property is used by the Master for count of master handlers.</description> </property>
3.1.2 hbase.client.write.buffer
HTable客户端的写缓冲的默认大小。这个值越大,需要消耗的内存越大。因为缓冲在客户端和服务端都有实例,所以需要消耗客户端和服务端两个地方的内存。得到的好处是,可以减少RPC的次数。我的配置如下:
<property> <!--htable.setWriteBufferSize(5242880);//5M --> <name>hbase.client.write.buffer</name> <value>5242880</value> </property>代码层面设置如下:
List<Put> putList = new ArrayList<Put>(); for (RowData row : tableData.getRows()) { if (null == row.getColumns() || 0 == row.getColumns().size()) continue; Put put = new Put(row.getRowKey()); for (ColumnData column : row.getColumns()) { put.add(column.getFamily(), column.getQualifier(), column.getValue()); } put.setDurability(Durability.SKIP_WAL); putList.add(put); } //采用批量提交,不要一条提交一次 //更好的建议是,能根据rowkey对list进行分组,rowkey对应为同一预分区的放同一list,然后提交list,这样速度更快 table.put(putList);
注意:
1)采用批量提交,不要一条提交一次
2)更好的建议是,能根据rowkey对list进行分组,rowkey对应为同一预分区的放同一list,然后提交list,这样速度更快
3.1.3 HBASE_HEAPSIZE
修改hbase-1.2.1/conf/hbase-env.sh中HBASE_HEAPSIZE,我的配置如下:
export HBASE_HEAPSIZE=4G
注意:你得首先使用64为JDK,64为操作系统和64为Hadoop以及64为hbase环境。
3.2 关于建表预分区
上图说明的问题:
1)创建表指定和不指定预分区是有本质区别的;
2)创建表不指定预分区,hbase默认只创建一个区,默认区大小为4GB,最开始读写数据都在这一个区,而这个区只是在集群一台机器上有,造成集群中单台机器负载过大,而其他机器都一直空闲;当文件大于4GB时,hbase暂停几分钟用来做split和compact,分裂为两个区,但新的数据写全部又集中到新的第二区,问题依旧是其他机器空闲;
3)创建表指定预分区,数据会根据提供的rowkey与建表时预分区做对比,将数据分布到不同预分区读写,达到负载均衡
结论:
建表必须指定预分区才能提高hbase并发读写性能,否则,就别玩hbase了。
3.3 关于表的ROWKEY设计
hbase默认是一级索引,一级索引指的是hbase对于rowkey方面的精确查询和范围查询都是很快的,所以,你用hbase尽量要将你的关注点设计到rowkey里面去。
也补充下哈,hbase目前外面也有开源的二级索引,比如华为的hindex —— 来自华为的 HBase 二级索引
上图是一个电话拨打记录存hbase的例子,说明问题如下:
1)不是有了预分区就行了的,rowkey的设计很关键,设计不合理,仍然会导致数据倾斜;
2)rowkey设计尽量达到数据的均匀分布