目录

前言

RowKey设计

设计原则

解决热点问题

Salt加盐

Reverse反转

Hash散列或Mod取余


HBase系列:


前言

上一篇中我们提到了HBase的读写原理,可以看出HBase是为写操作优化,更适合写多读少的场景,尤其是因为数据按列族和Region切分成一个个的StoreFile,在跨多文件查询数据的时候就会很慢。同时,由于Region切分策略,会让HFile出现数据倾斜的情况,因此我们在实际应用中首先要先设置预分区,指定HBase表有几个分区,每个分区内的RowKey范围,然后我们只要将RowKey的值尽可能均匀的放置在这些Region内即可。本篇我们就来介绍如何通过RowKey的设计提升HBase的读性能。

前面的文章中也提到,HBase只能通过RowKey查询数据:指定RowKey查询、指定RowKey区间查询、全表扫描。所以通常我们也会利用第三方组件如solr,elasticsearch对HBase做二级索引,提升查询效率,在后面的文章中再具体介绍。

RowKey设计

设计原则

Rowkey设计的优劣直接影响读写性能,HBase中的数据是按照RowKey的ASCII 字典顺序进行全局排序。ASCII码表:

hbase多对多 hbase多条件查询rowkey设计_hbase

RowKey设计应遵循以下原则:

长度原则

RowKey是一个二进制存储的值,RowKey的长度尽量控制在10~100个字节,建议是越短越好。 原因如下:

  • HFile 按照KeyValue存储,如果RowKey过长比如500个字节,1000万列数据光是RowKey就要占用500*1000万=50亿个字节≈5GB数据,非常影响HFile的存储效率;
  • MemStore中维护着Flush之前的数据,如果RowKey字段过长的话会占用很多内存,导致系统无法缓存更多的数据,影响查询效率;

唯一原则

由于RowKey用来唯一标识一行记录,所以必须在设计上保证RowKey的唯一性:

  • HBase中数据存储是Key-Value形式,若HBase中同一表插入相同Rowkey,则原先的数据会被覆盖掉(如果表的version设置为1的话),所以务必保证Rowkey的唯一性;

排序原则

HBase会把RowKey按照ASCII进行自然有序排序,所以反过来我们在设计RowKey的时候可以根据这个特点来设计完美的RowKey,好好的利用这个特性就是排序原则;

散列原则

在上面也提到,只要我们尽量将数据均衡的分布在每个Region内,就可以预防数据倾斜的情况。假如按照时间戳作为rowkey的前缀会导致大量数据堆积在一个RegionServer上导致Region热点问题,当大量读写请求到该RegionServer上时会对该RS的负载压力过高从而影响性能甚至出现故障;

解决热点问题

解决RegionServer热点现象需要良好的RowKey设计,让数据尽可能均匀的分布在每个Region下,通常有三种方案:加盐、反转、散列。 

Salt加盐

在原RowKey的前面添加固定长度的随机数,也就是给RowKey分配一个随机前缀使它和之前的RowKey的开头不同。

:在一个有3个Region以(,h)、[h,x)、[x,z)为Region分区的HBase表中,有下面三个rowkey:wykcsdn001,wykcsdn002,wykcsdn003 ,这三个rowkey会被分布在[x,z)这个region内,加盐后变成qwe_wykcsdn001,asd_wykcsdn002,zxc_wykcsdn003,这三个rowkey会被均匀分布在三个region分区内。

wykcsdn001-->qwe_wykcsdn001

wykcsdn002-->asd_wykcsdn002

wykcsdn003 -->zxc_wykcsdn003

加盐之后的吞吐量是之前的三倍,但加盐也有缺点:盐是随机字符串,在查找的时候不知道该盐的内容,读这些数据时需要耗费更多的时间,所以加盐增加了写操作的吞吐量,不过缺点是同时增加了读操作的开销。

Reverse反转

针对固定长度的Rowkey进行反转,将Rowkey中经常改变的部分放在最前面,可以有效的随机Rowkey。典型的比如手机号,时间戳这类数据前缀几乎都是一样的,最后几位更有随机性。反转之后得到的字符串即保证了随机性又不会像加盐一样无法得知rowkey的真实值。但反转也牺牲了Rowkey的有序性。

182xxxx7890-->0987xxx281

182xxxx6379-->9736xxx281

182xxxx1355-->5531xxx281

20200911145043-->34054111900202

20200911145058-->85054111900202

20200911145501-->10554111900202

Hash散列或Mod取余

hash比较好理解,将原来的rowkey内容或部分前缀通过hash算法(MD5、sha1、sha256、sha512)生成更加随机的字符串。相比于加盐的方式,hash后的字符串既可以使负载分散到整个集群,又可以通过原rowkey的值算出hash值来读取数据。

对于纯数字型的rowkey,也可以使用mod取余的方式来将其打散。

wyk001-->66079de6861d926bcd08da5878283601

wyk002-->344fd201bd135f5ad7d45ad5668e1438

wyk003-->81264b3ace502fec8c76a6991c0eeaed

123456789%21-->15

123459999%21-->12

123458888%21-->14

在工作中,我们也可以结合项目的实际情况结合这几种方式来设计RowKey,以预防Region热点。