#### 前言
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.7ENGINE_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.71)查问某段时间内的所有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