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的存储)