当前位置: 代码迷 >> 综合 >> RegionServer columnFamily设计与rowkey设计
  详细解决方案

RegionServer columnFamily设计与rowkey设计

热度:84   发布时间:2024-03-08 03:22:50.0

Hbase-之RegionServer columnFamily设计与rowkey设计

1 前言

参考官网地址

本文主要讲解region的大小,内存的大小,HDFS的备份因子对Hbase的集群影响,最终的结果就是你实际需要的内存往往比你想象中的要多。

“Lars Hofhansl说,就我个人而言我只会给我Hbase的每台服务节点配置6T左右的磁盘空间(除非你需要面临大量读操作的工作负载),同时Java Heap堆内存保证在32G,保证20个region,128M的memorystore,其它的资源配置保持默认。”

在这里插入图片描述


2 关于column family的数量

Hbase不能很好的处理超过2个或者3个Column family,所以请保持你schema创建的时候预先将Column Family的数量保证在一个较小的范围(<=2或者3比较好)。

目前,flush和compaction是在Region级别的基础上进行的,(一个Region代表一个Column Family的连续数据片段),所以当一个ColumnFamily的一个region中承载大量需要Flush的数据,即使相邻的Column Family需要flush的数据量特别小的时候,此时不管你是那个family,所有family的region数据都会被flush磁盘文件,此时会频繁的产生大量的文件,当大量的Column Family都进行flush数据到StoreFile的时候,此时flush和compaction的交叉作用会造成大量不必要的的IO开销。可以通过将flush和compaction改成Column Family级别,此时只有当该Column Family中需要flush data的 region数量达到一定数量才会进行统一的flush和compaction,这样就很明显减少了IO的次数

如果可以,可以尝试在同一时间只操作一个columnfamily,只有当需要将数据访问细致到column级别的时候才引入使用第二或者第三列簇。

2.1 table中有多个column family情况下行数的影响

当一个table中有多个column family的时候,请注意每个column family的行数,举个栗子。

Table

ColumnFamilyA - 100万行

? ColumnFamilyB - 10亿行

因为B的原因,A的数据也会被划分出许多region,而且分布上不同的regionserver上,这使得原本应该scan很快的A出现scan效率低下的情况。

3 Rowkey的设计

rowkey的设计主要是防止热点访问遵循以下特点:

  • 唯一原则
  • 排序原则
  • 散列原则

See schema.casestudies 查看rowkey设计的案例

3.1 热点数据rowkey

row在Hbase中按照rowkey字典顺序排序,这个设计是对scan的一种优化,这就能保证你将相关的数据统一连续存储在一起,scan读取的时候也是一起读取,当在同一时间用户量少的时候比较方便,然而,对于热点hotspotting访问的设计在Hbase中是少之又少的,当多个用户同时传输热点数据时,这些数据都存在集群中的一个或者少量的节点中,这种访问不管是read还是write或者其它的操作,都会压垮管理那些region的机器,造成性能急剧下降,还可能造成region unavalialble或者繁忙的问题。这还会对该regionserver中的其它region造成不利影响,因为该主机已经不发满足用户的负载。

所以设计数据访问模式很重要,这样才能充分,均匀地利用集群

3.2 防止write的时候造成热点

将那些真正需要放在同一个region中的数据的rowkey进行设计,但是从更大的角度讲,要将所有数据写入集群中的多个regions而不是仅仅一个region中。

下面开始介绍一些通用的rowkey设计以及他们的优缺点。

3.2.1加盐salting

加盐简而言之就是将随机数添加在rowkey的开头,保证随机分布存储真实rowkey,需要的前缀的数量根据你想将数据分成多少个region决定。

  • 下面的例子会解释salting怎样将数据写入并存储在不同的region server中,同时会说明该设计对read的负面影响。

假设你有以下的rowkey列表,并且对表进行了与分区,‘a’开头的是一个region,‘b’开头的是一个区域,在此表中,以‘f’开头的rowkey都分配在同一个region中。

案例1
foo0001 
foo0002 
foo0003 
foo0004

现在需要将它们分布在不同的区域中,你决定使用不同的4种盐a,b,c,d,这种情况下这些字母前缀种的每个字母都将根据不同分区的startkey和endkey分布在不同的region,在加盐salting之后,将改成以下rowkey,由于你现在讲数据写入到四个单独的region,从理论上讲,写入的吞吐量是写入一个分区的4倍.

a-foo0003 
b-foo0001 
c-foo0004 
d-foo0002

然后你添加另一行,该行的rowkey与实际已存在的rowkey相同,则会随机为其分配4个可能的盐值之一,如下

a-foo0003 ##
b-foo0001 
c-foo0003 ##
c-foo0004 
d-foo0002
salting缺点

由于分配是随机的,因此,如果按照字典顺序检索row,则需要做更多的操作,这样Get的时候还是会对相同后缀的rowkeys进行很多其它操作(因为实际上相同的rowkey对应的Cell存了多份,我们需要取最新的一份),所以对read不是特别友好,这个得权衡利弊,看是想写入更快还是读的时候更快。

3.2.2 hash散列

相比随机加盐添加前追,你还有一种方式可以将一个给定的row始终按照相同的前缀保持一个被加盐的状态,这样也可以将数据负载均衡到不同的regionserver上防止热点访问,而且保证可以预测的read,使用确定性hash允许客户端重建完整的rowkey,然后使用Get操作精准获取准确的值.

那么什么是hash?

#假如此时有3行rowkey
abc001
abc002
abc003我们对每个rowkey进行hash,此处我们利用md5算法三列算法对rowkey进行处理取前4位,作为rowkey的前缀,结果如下:9bf0-abc001 (abc001在md5后是9bf049097142c168c38a94c626eddf3d,取前4位是9bf0)
7006-abc002
95e6-abc003
#如果Rowkey是数据类型,可以使用Mod方法,自行百度吧弟弟们

3.2.3 rowkey反转

第三种防止热点的方式就是将rowkey中的固定长度的字段进行反转或者将数据字段进行反转举个例子:

001abc
002abc
003abc#将前三位反转,(通常使用变化最频繁的属性进行反转)这样达到了散列分布的效果,但是牺牲了行正常排序的属性
100abc
200abc
300abc

4 Rowkey设计的注意点

  • 尽量不要单调递增的添加rowkey相关的数据如:按时间戳递增插入
  • rowkey尽量不要超过16KB,不然占用太多的磁盘空间和IO资源(因为每个Cell都会伴随着单独rowkey的存储)