hbase读写性能优化一般可以从三个方面入手
1、hbase服务端读写配置
2、hbase客户端配置
3、hbase表的设计
本文从表设计的rowkey和预分区角度优化hbase读写性能,避免region读写热点问题。
一、hbase数据读取方式
先了解hbase读取数据方式:
1、随机读:通过get方式,指定rowkey获取唯一记录
2、局部顺序读(随机读+顺序读):通过scan方式,设置startRow和stopRow参数进行范围匹配
3、顺序读(全表顺序读):通过scan方式,全表扫描,并通过Filter过滤出数据
二、rowkey设计思路
hbase数据分成多个region存在于集群各机器上,region的数据边界是startkey和endkey,所以设计一个好的rowkey,使读写请求均匀落在各个region上尤为重要。
rowkey设计思路大致有以下几种:
1、随机
取一个随机数作为rowkey,如new Random().nextLong()
读取方式:只支持全表扫表,无法支持随机读
2、哈希
取业务ID的哈希值作为rowkey,如hash(url)
读取方式:支持随机读和顺序读,不支持局部顺序读
3、哈希+业务ID(推荐)
对业务ID取哈希,再拼接业务ID,如hash(url)+url
读取数据:支持随机读、局部顺序读、顺序读
三、预分区
hbase表预分区
避免读写热点:hbase表预分区设计,加上rowkey的合理设计,使得读写数据请求分散在多个region上。
提前预防region分裂:hbase表的单个region超过一定大小后,会进行分裂,分裂后的major compaction会占用大量的系统资源(CPU,IO,内存,带宽),导致读写延迟,并且compaction极有可能导致写阻塞。
语法:
指定预分区数目和分区策略
create 't1', 'f1', {NUMREGIONS => 5, SPLITALGO => 'HexStringSplit'}
指定分区rowkey,rowkey是前一个分区的stopKey,后一个分区的startkey,第一个分区没有startkey,最后一个分区没有stopkey
create 't1', 'f1', SPLITS => ['1', '2', '3', '4']
以文件形式指定分区的rowkey
create 't1', 'f1', SPLITS_FILE => 'splits.txt'
在splits.txt中,每一行为一个rowkey
1
2
3
4
四、案例分析
需求:往hbase一张表写入大概800G的网页数据,以url作为业务ID,同一个站点的数据聚集写入。
分析:hbase默认每个region的最大大小10G,每个region预留空间20%,一个region可存储数据为8G,800/8=100,所以预分区数目为100。
以url为业务ID,且同一个站点数据一起写入,如果直接以url作为rowkey,则短时间内所有写入请求都落在一个region上,造成写热点,所以,对url适当处理按照 哈希+业务ID 的方式处理比较合适。
region分区文件可以设计如下:
01
02
03
......
99
总共99行,分成100个区,每个分区中rowkey的前缀为一个固定的两位数字(注意01-09前面补0了)。
哈希处理:
前缀prefix=hash(url)%(expectRegionNum),可以采用字符串默认哈希值对expectRegionNum取余。
最终的rowkey=prefix+url
支持读取方式:
随机get:以上述相同的方式获得url的rowkey,然后进行get
局部顺序读:指定读取的url范围为url1~url2,需要分别扫描落在各个前缀区间的数据,如落在以005前缀的区间内,扫描时的startkey=005url1,stopkey=005url2,循环处理[00-99]各个前缀,即可完成对url1~url2区间内数据的扫描。(该读取方式还是有一点点复杂)
全表顺序读:无需讲解。