问题描述:
Hbase在大规模数据数据集情况下拉取数据时,若rowkey密集集中在一台节点,则在批量拉取数据时容易出现数据拉取速度很慢或者出现timeout,如果资源允许的情况下,可以将rowkey根据自己的规则手动split到多个分区中,从而把rowkey均匀打到多台服务器,这样在数据获取时就不会因为rowkey集中而对单台hbase服务器压力过大导致超时影响任务执行。
Hbase rowKey
先看一下写入hbase的基本语法与addColumn源码。put方法,这里第一行即为我们传入的rowKey,通过addColumn方法分别添加列簇famliy,标识qualifier还有值value。这里只需要知道split分区需要用到的rowKey就是我们put方法写入Hbase表的rowKey。
val put: Put = new Put(Bytes.toBytes(rowKey))
put.addColumn(Bytes.toBytes(aaa), Bytes.toBytes(bbb), Bytes.toBytes(ccc))
public Put addColumn(byte[] family, byte[] qualifier, byte[] value) {
return this.addColumn(family, qualifier, this.ts, value);
}
Hbase 建立分区表
首先根据自己的Hbase服务器调用HbaseConfiguration配置好quorum,port等参数,然后建立连接获取admin,在建表时加入splitKeys即可。
1)这里splitkeys是基于先验信息得到的,即你已经对自己写入Hbase表中的rowkey分布有大致了解,如果还不了解,可以事先随机采样一部分做等距或等分布的方法找到合适的划分区间作为自己分区划分的依据
2)由于hbase是基于byte来操作,所以相应的splitkeys需要转换为字节的形式
3)建表完成后,put数据进去后就会根据splitkeys与相应的quorum配置,均匀的打到各台hbase服务器上
def getHbaseRegion(tableName: String): Unit ={
val zookeeper_quorum = "quorum"
val zookeeper_port = "port"
val zookeeper_sava_path = "sava_path"
val conf = HBaseConfiguration.create()
conf.set("hbase.zookeeper.quorum", zookeeper_quorum)
conf.set("hbase.zookeeper.property.clientPort", zookeeper_port)
conf.set("zookeeper.znode.parent", zookeeper_sava_path)
val connection: Connection = ConnectionFactory.createConnection(conf)
var admin: HBaseAdmin = connection.getAdmin.asInstanceOf[HBaseAdmin]
val splitKesy = Array(2, 4, 6, 8).map(Bytes.toBytes(_))
if (admin.tableExists(tableName)){
println("Warning: table is already exists")
}
val tName = valueOf(tableName)
//创建Hbase表模式
val descriptor = new HTableDescriptor(tName)
descriptor.addFamily(new HColumnDescriptor("cf"))
//创建表
admin.createTable(descriptor,splitKesy)
}
结果
分区并put数据得到新的分区表,可以看到rowkey的分布很均匀,再次拉取数据未出现超时的情况发生。