HBase表rowKey设计原则

rowkey设计首先应当遵循三大原则:

rowkey长度原则

rowkey是一个二进制码流,可以为任意字符串,最大长度为64kb,实际应用中一般为10-100bytes,它以byte[]形式保存,一般设定成定长。

一般越短越好,不要超过16个字节,注意原因如下:

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

2、hbase将部分数据加载到内存当中,如果rowkey过长,内存的有效利用率就会下降。

rowkey散列原则

如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位字节采用散列字段处理,由程序随即生成。

低位放时间字段,这样将提高数据均衡分布,各个regionServer负载均衡的几率。

如果不进行散列处理,首字段直接使用时间信息,所有该时段的数据都将集中到一个regionServer当中,这样当检索数据时,负载会集中到个别regionServer上,造成热点问题,会降低查询效率。

rowkey唯一原则

必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。

但是这里的量不能太大,如果太大需要拆分到多个节点上去。

所以良好的rowkey设计,应当遵循三大原则,并且能让数据分散,从而避免热点问题。

1.1 加盐

这里所说的加盐并非密码学中的加盐,而是在rowkey的前面分配随机数,当给rowkey随机前缀后,它就能分布到不同的region中,这里的前缀应该和你想要数据分散的不同的region的数量有关。

1.2 预分区

通常hbase会自动处理region拆分,当region的大小到达一定阈值后,region将被拆分成两个,之后在两个region都能继续增长数据。

然而在这个过程当中,会出现两个问题:

第一点,就是我们所说的热点问题,数据会继续往一个region中写,出现写热点问题;

第二点,则是拆分合并风暴,当用户的region大小以恒定的速度增长,region的拆分会在同一时间发生,因为同时需要压缩region中的存储文件,这个过程会重写拆分后的region,这将会引起磁盘I/O上升 。

压缩:hbase支持大量的压缩算法,而且通常开启压缩,因为cpu压缩和解压的时间比从磁盘读写数据的时间消耗的更短,所以压缩会带来性能的提升。

对于拆分合并风暴,通常我们需要关闭hbase的自动管理拆分。然后手动调用hbase的split(拆分)和major_compact(压缩),对其进行时间控制,来分散I/O负载。

但是其中的split操作同样是高I/O的操作。

为了解决这些问题,预分区就是一种很好的方法,通常它和加盐结合起来使用。

所谓预分区,就是预先创建hbase表分区。这需要我们明确rowkey的取值范围和构成逻辑。

1.3 哈希

细心的同学可能会发现,在我们刚刚提出的加盐与预分区rowkey设计方法中,并没有完整运用到rowkey设计的散列原则。

更一步思考下,我们会发现如果只运用加盐与预分区rowkey设计方法,数据会真正无序随即分布在hbase集群当中,这并没有让我们利用到hbase根据字典顺序排序的这一特点。

由此,哈希这一设计理念便顺理成章的出现在我们眼前。

1.4 反转

对于以手机号码这样比较固定开头的rowkey(例如开头177,159,138),但是它的后几位都是随机的,没有规律的。我们可以将手机号反转之后作为rowkey,

这样就避免了热点问题。

这就是rowkey设计的另一种方法反转,通过反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。

这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。

 

posted @ 2021-03-08 10:46  lenomail  阅读(131)  评论(0编辑  收藏  举报