1.从表的设计
从表的设计方面来讲可以对rowkey、Column Family、region分区进行优化,具体到rowkey有rowkey的长度不能太长,实际应用中一般为10~100bytes;rowkey是根据字典序排列的可以将一起读取的数据存储到一块。还可以利用散列,对rowkey做相应的处理。对于列族,一张表里的列族的最好不要超过3个,一般来说是1-2个。
关于region分区是预先创建一些空的regions,这样当数据写入HBase时,会按照region分区情况,在集群内做数据的负载均衡。
2.写表操作方面有
多HTable并发写,创建多个HTable客户端用于写操作,提高写数据的吞吐量; 对HTable参数设置进行相关设置;比如通过调用HTable.setAutoFlush(false)方法可以将HTable写客户端的自动flush关闭,这样可以批量写入数据到HBase,而不是有一条put就执行一次更新。
通过调用HTable.setWriteBufferSize(writeBufferSize)方法可以设置HTable客户端的写buffer大小。对于相对不太重要的数据,可以在Put/Delete操作时,通过调用Put.setWriteToWAL(false)或Delete.setWriteToWAL(false)函数,放弃写WAL日志,从而提高数据写入的性能。
3.读表操作
创建多个HTable客户端用于读操作,提高读数据的吞吐量。
HTable参数设置:通过调用HTable.setScannerCaching(int scannerCaching)进行配置,设置HBase scanner一次从服务端抓取的数据条数,一个合理的值(默认情况下一次一条)。scan时指定需要的Column Family,可以减少网络传输数据量。
批量读:通过调用HTable.get(List)方法可以根据一个指定的row key列表,批量获取多行记录,这样做的好处是批量执行,只需要一次网络I/O开销
4.RowKey设计
一条数据的唯一标识就是rowkey,那么这条数据存储于哪个分区,取决于rowkey处于哪个一个预分区的区间内,设计rowkey的主要目的 ,就是让数据均匀的分布于所有的region中,在一定程度上防止数据倾斜。接下来我们就谈一谈rowkey常用的设计方案。
- 生成随机数、hash、散列值
比如:
原本rowKey为1001的,SHA1后变成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7
原本rowKey为3001的,SHA1后变成:49042c54de64a1e9bf0b33e00245660ef92dc7bd
原本rowKey为5001的,SHA1后变成:7b61dec07e02c188790670af43e717f0f46e8913
在做此操作之前,一般我们会选择从数据集中抽取样本,来决定什么样的rowKey来Hash后作为每个分区的临界值。 - 字符串反转
20180524000001转成10000042508102
20180524000002转成20000042508102
这样也可以在一定程度上散列逐步put进来的数据。 - 字符串拼接
20180524000001_a12e
20180524000001_93i7
5.其他相关优化
设置RPC监听数量
hbase-site.xml
属性:hbase.regionserver.handler.count
解释:默认值为30,用于指定RPC监听的数量,可以根据客户端的请求数进行调整,读写请求较多时,增加此值。
优化HStore文件大小
hbase-site.xml
属性:hbase.hregion.max.filesize
解释:默认值10737418240(10GB),如果需要运行HBase的MR任务,可以减小此值,因为一个region对应一个map任务,如果单个region过大,会导致map任务执行时间过长。该值的意思就是,如果HFile的大小达到这个数值,则这个region会被切分为两个Hfile。
优化hbase客户端缓存
hbase-site.xml
属性:hbase.client.write.buffer
解释:用于指定HBase客户端缓存,增大该值可以减少RPC调用次数,但是会消耗更多内存,反之则反之。一般我们需要设定一定的缓存大小,以达到减少RPC次数的目的。
不定期更新