Hbase的Rowkey设计以及如何进行预分区

今天有人问我Hbase的rowkey设计和预分区的问题,这篇文字就简单介绍一下.,关于Hbase的表的一些基本概念这里就不说了,直接说重点,尽可能说的简单一点,废话就不写了.

1.什么是Rowkey?

我们知道Hbase是一个分布式的、面向列的数据库,它和一般关系型数据库的最大区别是:HBase很适合于存储非结构化的数据,还有就是它基于列的而不是基于行的模式.

Hbase是采用K,V存储的,那Rowkey就是KeyValue的Key了,Rowkey也是一段二进制码流,最大长度为64KB,内容可以由使用的用户自定义。数据加载时,一般也是根据Rowkey的二进制序由小到大进行的。

HBase是根据Rowkey来进行检索的,系统通过找到某个Rowkey (或者某个 Rowkey 范围)所在的Region,然后将查询数据的请求路由到该Region获取数据。HBase的检索支持3种方式:

(1) 通过单个Rowkey访问,即按照某个Rowkey键值进行get操作,这样获取唯一一条记录;

(2) 通过Rowkey的range进行scan,即通过设置startRowKey和endRowKey,在这个范围内进行扫描。这样可以按指定的条件获取一批记录;

(3) 全表扫描,即直接扫描整张表中所有行记录。

HBASE按单个Rowkey检索的效率是很高的,耗时在1毫秒以下,每秒钟可获取1000~2000条记录,不过非key列的查询很慢。

2.Rowkey的作用?

(1),读写数据时,通过rowkey找到对应的region.

(2),MemStore中的数据按照rowkey字典顺序排序.

(3),Hfile中的数据按照rowkey字典顺序排序.

3.Rowkey的长度原则?

Rowkey是一个二进制码流,Rowkey的长度被很多开发者建议说设计在10~100个字节,不过建议是越短越好,不要超过16个字节。

原因如下:

(1)数据的持久化文件HFile中是按照KeyValue存储的,如果Rowkey过长比如100个字节,1000万列数据光Rowkey就要占用100*1000万=10亿个字节,将近1G数据,这会极大影响HFile的存储效率;

(2)MemStore将缓存部分数据到内存,如果Rowkey字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此Rowkey的字节长度越短越好。

(3)目前操作系统是都是64位系统,内存8字节对齐。控制在16个字节,8字节的整数倍利用操作系统的最佳特性。

4.Rowkey的散列原则?

如果Rowkey是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将Rowkey的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个Regionserver实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有新数据都在一个 RegionServer上堆积的热点现象,这样在做数据检索的时候负载将会集中在个别RegionServer,降低查询效率。

其实总结就一句话:要结合业务数据的特点,并考虑高频查询,尽可能的把数据打散到整个集群.

5.Rowkey的设计?

(1).Salting.

                                salting的原理是把固定长度的随机数放在行键的起始处.

Hbase的Rowkey设计以及如何进行预分区_第1张图片

优缺点:由于前缀是随机生成的,所以如果想要按照字典顺序找到这些行,就比较的麻烦,salting增加了写操作的吞吐量,但是也增大了读操作的开销,而且由于前缀是随机的,也没有办法按照Rowkey去查询一行数据.

(2),Hashing

                         hash的原理是将rowkey记性hash计算,然后取hash后的部分字符串和原来的rowkey进行拼接.

Hbase的Rowkey设计以及如何进行预分区_第2张图片

优缺点:可以一定程度上打散整个数据集,但是不利于scan操作,由于不同数据的hash值有可能相同,所以在实际应用中,一般会使用md5计算,然后截取前几位的字符串.

examples: substring(MD5(设备ID),0,x) + 设备的ID,x一般会取5到6位.

(3).Reversing

                                                        reversing的原理是反转一段固定长度或者全部的键.

Hbase的Rowkey设计以及如何进行预分区_第3张图片

优缺点:有效的打乱了行建,但是牺牲了行排序的属性.

5.为什么要预分区?

我们知道一个hbase的被划分了n个region,被托管在RegionServer中,region中有两个重要的属性,startkey和endkey,它表示的是这个region管理的rowkey的范围,读写数据的时候,会根据rowkey找到在哪个startkey-endkey之间,从而找到了数据在哪个region上那么问题来了,在我们创建一张表后,默认只有一个region,也就是说所有的数据都会写到这个一个region上,当数据量大到超过一个region的大小时(一个region默认是10G),就会发生region-split,也就是把一个region从中间一分为二,分成两个region,依次类推.这个时候就会产生热点问题.

6.什么是热点?

HBase中的行是按照rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。然而糟糕的rowkey设计是热点的源头。热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region,由于主机无法服务其他region的请求。设计良好的数据访问模式以使集群被充分,均衡的利用。

为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个。所以我们就要进行预分区,把数据写到多个region,在加上随机散列,就能解决热点问题,极大的提高性能.

7.预分区多少个呢?

要多少个预分区是根据数据量而定的,一个region的默认大小是10G,当然了我们也可以调整这个大小,你要先算出要存数据的大小,然后决定建多少个分区.

困了,明天接着写吧.

如果有写的不对的地方,欢迎大家指正,如果有什么疑问,可以加QQ群:340297350,谢谢

 

你可能感兴趣的:(hbase)