hbase表的设计

来源:互联网 发布:大草原上的小老鼠 知乎 编辑:程序博客网 时间:2024/05/21 08:51

一、预分区的设计

hbase默认建表时有一个region,该region没有startkey和endkey,在向该表中写数据时都会写入到唯一的一个region中

随着数据量的增加,此region中某个store下的storeFile文件的大小达到一定阈值(动态阈值)会进行split分割,一分为二

在此过程中,会产生两个问题需要解决: 

1、在region进行split分割前会产生热点问题 

同一时间可能整个hbase集群只有一个或几个regionserver在响应客户的读写请求

2、region在被动执行split时会offline,另外会消耗大量的集群资源,导致整个hbase集群访问不稳定

如何解决: 

提前对hbase表的region指定个数,并且指定每个regionrowkey范围,降低被动split分割的几率---预分区

 

建表时创建预分区的方式

方式1

>create 't001', 'f1', SPLITS => ['10', '20', '30', '40']

创建出的region会被master随机分散在regionserver上  

startkey endkey  

region1 10

region2 10 20

region3 20 30

region4 30 40

region5 40

 

插入数据,使用不同的rowkey

> put 't200','33','f1:name','tom'    --

regionstartkeyendkey的范围是对插入数据时的rowkey前缀进行匹配 

> put 't200','30','f1:name','tom'(左闭右开)

 

方式2

>create 't002', 'f1', SPLITS_FILE => '/home/hcx/demo/splits.txt'

 

 

方式3

使用自带的api预定义类分割算法

> create 't003', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}

适用场景:

rowkey的前缀是十六进制字符串的场景

 

二、rowkey的设计 

rowkey的设计主要是为了避免数据倾斜,数据热点

热点:同一时间内大量的数据读写io都集中在某一台或几台regionserver上  

例如

> create 't001', 'f1', SPLITS => ['10', '20', '30', '40']

如果向t001中插入数据

rowkey的设计的如下:

如果使用一个时间戳+随机字符串作为rowkey的话?  

151056426132_afdd3243

热点问题 -》大量的数据会写入到region2中,同一时间只有region2所在的regionserver响应写请求  

如何设计:

Rowkey — 两位00-50之间的随机数据_时间戳_随机字符串

rowkey设计时的要点: 

必须唯一,不能重复 

rowkey的长度:

官方 -10-100字节之间

实际-》  16字节以下  

hbase中每个cell中都存在rowkey+列簇+

列簇和列名名称也需要短小  

避免数据热点和倾斜  

rowkey设计时要遵循一个【散列原则

将要插入的数据的rowkey散列的分布在各个region中  

满足业务需求!!!  

【散列原则】的一般思路:

1生产随机字符串

crc32/md5可以生产随机数字或字符串  

一般不会对rowkey全部使用随机字符串  

随机数字+日期/订单id +随机数字

2反转字符串

正常时间戳

1510564261322

1510564261335

1510564266388

如果将以上时间戳直接作为rowkey容易产生热点问题

反转后时间戳

2231。。。0151

5331。。。。0151

8836。。。。0151

反转之后将变化比较大的低位反转到字符串的开头

hbase默认支持前缀匹配,进行前缀匹配时会进行散列分布 

使用场景:

数字是连续的rowkey场景

时间戳/日期/手机号码/连续的订单id   

20171114110526

20171114110526

3拼接字符串

固定长度的数字+固定长度的随机字符串   

日期+随机:

2017101411_fer3435df

2017111411_fer3435df

2017111411_ferghghdf

2017111412_fe5656hdf

2017111510_fesds56hd

2017121810_fesds56hd

1如何根据以上rowkey查询11月份的话单记录

Scan  scan = new Scan() ;

scan.setStartKey("201711") ;

scan.setStopKey("201712") ;

2如何根据以上rowkey查询1115的话单记录

Scan  scan = new Scan() ;

scan.setStartKey("20171115") ;

scan.setStopKey("20171216") ;

【电话话单rowkey设计案例】

每天用户的话单记录可能几十亿条  

每条话单记录里包含很多字段

业务要求:

根据客户的电话号码和时间范围快速查询个人的话单记录

如何满足:

1、如何从一张bhase大表中快速查询出个人的话单记录

   本身个人的话单数据相对整个hbase大表数据量非常小

   组好将个人的数据放入到一个region中,避免数据散列

   这样可以减少region的寻址次数及regionserver的响应次数

2rowkey如何设计?

   考虑要点:

 避免数据散列

 客户可以根据电话号码+时间范围查询数据

 rowkey

   电话号码_日期_随机字符串

   电话号码在前可以保证个人的数据在表中存储的连续性,避免数据散列

   日期可以通过前缀匹配查询出个人某个时间范围内的话单

   随机字符串为了保证rowkey的唯一性

1390000000_2017101411_34fgf      138xxxxx  1.5  5   

1390000000_2017111411_34fgf      138xxxxx  1.5  5

1390000000_2017121411_34fgf      138xxxxx  1.5  5

1查询11月份的话单记录:

Scan  scan = new Scan() ;

scan.setStartKey("1390000000_201711") ;

scan.setStopKey("1390000000_201712") ;

2查询1120的话单记录:

Scan  scan = new Scan() ;

scan.setStartKey("1390000000_20171120") ;

scan.setStopKey("1390000000_20171121") ;

原创粉丝点击