关于nosql:HBase的RowKey设计原则含案例全

11次阅读

共计 4783 个字符,预计需要花费 12 分钟才能阅读完成。

#### 前言

HBase 的 RowKey 的行由行键按字典程序排序,这样的设计优化了扫描,容许存储相干的行或者那些将被一起读的邻近的行。然而,设计不好的行键是导致 hotspotting 的常见起因。当大量的客户端流量(traffic)被定向在集群上的一个或几个节点时,就会产生 hotspotting。这些流量可能代表着读、写或其余操作。流量超过了承载该地区的单个机器所能负荷的量,这就会导致性能降落并有可能造成地区的不可用。在同一 RegionServer 上的其余地区也可能会受到其不良影响,因为主机无奈提供服务所申请的负载。设计使集群能被充沛平均地应用的数据拜访模式是至关重要的。

为了避免在写操作时呈现 hotspotting,设计行键时应该使得数据尽量同时往多个 RegionServer 上写,而防止只向一个 RegionServer 写,除非那些行真的有必要写在一个 RegionServer 里。HBase 的排序问题按字典序 rowkey 排序, 从小到大, 如果工作为了取得最新的工夫数据可用用工夫戳反转, 或者用 long.maxvalue – timestamp

#### 设计准则
依照 散列 惟一 长度 程序

散列

散列和预分区能够放在一起 比方事后分 10 个 region  缩小热点问题

能够将 id %10 做结尾 然而如果 id 规律性强的话 能够用(id+ 年月日)%10

惟一

必须在设计上保障其唯一性,rowkey 是依照字典程序排序存储的,因而,设计 rowkey 的时候,要充分利用这个排序的特点,能够将常常读取的数据存储到一块,将最近可能会被拜访的数据放到一块。能够用工夫戳放在其中 hbase 是按字典序排序 要思考始终单分区写状况

长度

rowkey 作为二进制码流最大为 64kb 最好不要超过 16 个字节 设计过长会占 memstore 空间

程序 

HBase 的 rowkey 装置字典序顺序排列 从小到大, 所以须要最新数据时须要翻转工夫戳或者自增 id    

可枚举属性值较少的属性放在 rowkey 后面

rowkey 是由多个字段组合而成,这多个字段的先后秩序和拜访的效率有间接的关系。一个广泛的规定是:数量较少,可控的字段放在 rowkey 靠前地位(如 eengine_type,provinc 等);反之放在前面(如 vin,timestamp 等)。这样做的起因是可控属性放在后面,对各种不同查问需要的平衡性强一些,反之平衡性较差。

案例 1:YCK09360-60-1638290481900-9011D6L00124    434.7
 
YCK09360-60-1638290482900-9011D6L00124    76.1
 
YCK09360-60-1638290483900-9011D6L00124    18.6
 
YCK09360-60-1638290484900-9011D6L00124    150.1
 
YCK09360-60-1638290485900-9011D6L00124    96.1
 
YCK09360-60-1638290586900-9011D6L00124    35.7
ENGINE_TYPE 可枚举,并且数量较少,放在后面;而 vin 确很多,因而放在前面。这样的设计可能适应如下两种需要,复杂度都比拟小:1)查问, 某段时间内 YCK09360-60 的所有数据。这种需要设置 scan 的 startrow=‘YCK09360-60_工夫戳’,endrow=‘YCK09360-60_工夫戳’,即可。2)查问某段时间内的所有 9011D6L00124 的数据。这种需要下,依据 scan rowkey 间断的准则,这种需要设置 scan 的 startrow=‘YCK09360-60_工夫戳_9011D6L00124’,endrow=‘YCK09360-60_工夫戳_9011D6L00124’,即可。

然而,如果将 vin 放在后面,如下所示,适应性就差一些,如下所示案例 2:

9011D6L00124-YCK09360-60-1638290481900    434.7
 
9011D6L00124-YCK09360-60-1638290482900    76.1
 
9011D6L00124-YCK09360-60-1638290483900    18.6
 
9011D6L00124-YCK09360-60-1638290484900    150.1
 
9011D6L00124-YCK09360-60-1638290485900    96.1
 
9011D6L00124-YCK09360-60-1638290586900    35.7
1)查问某段时间内的所有 9011D6L00124 的数据。这种需要下,设置 scan 的 startrow=‘9011D6L00124-YCK09360-60- 工夫戳,endrow=‘9011D6L00124-YCK09360-60- 工夫戳’,即可。2)查问某段时间内 YCK09360-60 的所有数据。这种需要设置 scan 是要取的 YCK09360-60 小所有的 vin 号并放在 rowkey 的最前段, 启动多个 scan 去扫描多组数据
HBase 的 rowkey 装置字典序顺序排列 从小到大, 所以须要最新数据时须要翻转工夫戳或者自增 id  , 所以在应用工夫戳字段是最好是应用 long.maxvalue-timestamp/1000 , 这样保障最新的数据总是在较新的地位, 不便读取

预分区的设置也是由必要的, 避免数据热点问题., 能够应用 hash 取余的形式去要害分区字段, 保障了分区平均性

所以最初设计的计划

分区字段 - 标识字段 - 标识字段 -long.maxvalue-timestamp

其余我感觉有意义的点

缩小列族及缩小数据存储的开销, 必要时缩小限定符 , 间接将数据写成独自一条, 其余解决代码中进行宰割. 

在 HBase 中,value 永远和它的 key 一起传输的。当具体的值在零碎间传输时,它的 rowkey,列名,工夫戳也会一起传输。如果你的 rowkey 和列名很大,HBase storefiles 中的索引(有助于随机拜访)会占据 HBase 调配的大量内存,因为具体的值和它的 key 很大。能够减少 block 大小使得 storefiles 索引再更大的工夫距离减少,或者批改表的模式以减小 rowkey 和列名的大小。压缩也有助于更大的索引。管制 rowkey 在 16 个字节以下 并维持在 8 的整数倍, 合乎 64 位零碎的 8 字节对齐 , 最大不要超过 64 位

业务拜访中权重高的 key 放在后面

例如 URLRecords 表的主要用途是用来计算当天的 URL 拜访排名。依据业务需要,须要拜访某天的所有 URL,因而 date 是主键,权重更高,放在后面,而 URL 则放在前面。结构冗余数据

例如,percontent 的数据蕴含了 URL Records 的数据,URL Records 的数据是冗余存储的,区别在于 percontent 的 URL 放在 date 后面,而 URL Records 表的 URL 放在 date 前面。这就是因为 URL 在满足不同需要的时候,权重不同,因为 URL Records 须要的数据量不大,因而采纳冗余的机制解决该矛盾。衡量需要的重要性和零碎忍耐度抉择一种计划当两种需要有矛盾,但其中一方属于主要需要,并且在零碎忍耐度范畴之内的话,能够舍弃一种计划。优先满足需要更强的一方

Rowkey 的工夫属性问题

循环 key 应用(1)存在问题如果 rowkey 中有工夫属性,并且随着工夫的减少,rowkey 会一直的增大上来的话,会造成 region 数量一直地减少。如果应用 TTL 来控制数据的生命周期,一些老的数据就会过期,进而导致老的 region 数据量会逐步缩小甚至成为空的 region。这样一方面 region 总数在一直减少,另外一方面老的 region 在一直的成为空的 region,而空的 region 不会主动合并,进而造成过多空的 region 占用负载和内存耗费的状况。(2)解决办法这种状况下,能够应用循环 key 的办法来解决。思路是依据数据的生命周期设定 rowkey 的循环周期,当一个周期过来当前,通过工夫映射的办法,持续应用老的过期数据的 rowkey。例如,key 的格局如下:YY-MM-DD-URL。如果数据的生命周期是一年,则能够应用 MM-DD-URL 的格局。这样以后一年过来当前,数据曾经老化,后一年的数据能够持续写入前一年的地位,应用前一年数据的 rowkey。这样能够防止空的 region 占用资源的状况。依据 hbase 的原理,key 的周期须要至多比 TTL 大 2 * hbase.hregion.majorcompaction(默认 24 小时)的工夫,才可能保障过期的数据可能在 key 循环回来之前失去齐全清理。依照工夫周期进行建表的形式也能够解决空 region 的问题,和循环 key 办法相比拟,循环 key 的长处如下:操作简略,不须要反复建表,零碎主动解决

同样,循环 key 具备如下劣势:须要应用 TTL 来老化数据,可能会减少 compact 累赘

须要保障查问操作不会查问到过期数据,否则会影响零碎性能。如果在零碎压力不是特地大,须要长期运行,可能管制查问不会查问到过期数据的场景下,倡议应用 TTL+ 循环 key 的形式,否则倡议应用依照工夫周期进行建表的形式。通过 rowkey 设计来管制并发度
在雷同业务模式下,不同的 rowkey 设计零碎的并发度不一样。和按天建表的思路相似,通过 rowkey 管制并发度的准则是激活的 region 总数适中,每个 regionserver 的激活 Region 数大于 1,小于(写操作内存 /flushsize)为宜。为了实现这一点,能够将可枚举、数量无限的属性放在 rowkey 的后面,工夫放在前面的形式来进步并发度;通过将大粒度的工夫属性(如天、小时等)放在 rowkey 后面,数量很大的可枚举属性(如电话号码、URL 等)放在前面的办法来管制激活的 region 数。

电信手机行业案例

案例一
 
xx_yy_zz_工夫戳
 
xx 为分区字段 必须散列
 
yy 和 zz 为标识查问字段  若可枚举依照字段枚举个数从小到大 不便查问
 
工夫戳为最好查问字段标识
 
若表的用处是为了统计当天数据 能够将年月日放入 rowkey 并排在 yy 之前
 
场景题
 
应用场景:
 
电信案例: 查问某个人 (手机号) 某年 [某月某日](工夫) 的通话详情。1) 预分区
 
(1) 评估将来半年到一年的数据增长, 不让其主动分区(10G)
 
    (2) 确定分区键
 
    00| 01| 02| ...
 
    000| 001| ...
 
2) 设计 RowKey
 
(1) 确定分区号   (散列性)
 
    00_ 01_ 02_...
 
​
 
手机号 % 分区数            不够散列
 
(手机号 + 年月日)% 分区数   依照月份、年进行查问  不不便
 
    (手机号 + 年月)% 分区数
 
(2) 拼接字段     (唯一性、长度)
 
    XX_手机号_工夫戳
 
    XX_手机号_年月日 时分秒
 
    XX_工夫戳_手机号
 
    XX_年月日 时分秒_手机号
 
(3) 校验
 
    13412341234 2021-09-07
 
    XX_手机号_年月日 时分秒
 
    startRow:05_13412341234_2021-09-07
 
    stopRow :05_13412341234_2021-09-08
 
            05_13412341234_2021-09-07|
 
    XX_年月日 时分秒_手机号
 
    startRow:05_2021-09-07 00:00:00_13412341234
 
    stopRow :05_2021-09-08 00:00:00_13412341234
 
​
 
13412341234 2021-09  2021-11
 
XX_手机号_年月日 时分秒
 
    startRow:05_13412341234_2021-09
 
    stopRow :05_13412341234_2021-09|
 
            05_13412341234_2021-10
 
​
 
    startRow:03_13412341234_2021-10
 
    stopRow :03_13412341234_2021-11
 
​
 
    startRow:04_13412341234_2021-11
 
    stopRow :04_13412341234_2021-12  
正文完
 0