HBase Rowkey设计原则

RowKey是什么?

HBase中RowKey可以唯一标识一行记录,在HBase查询时会有几种形式:

 1 通过get方式,指定RowKey获取唯一一条记录。
 2 通过scan方式,设置startRow和stopRow参数进行范围匹配。
 3 全表扫描,直接扫描整表所有数据。
RowKey字面上来看,就是行键意思,在增删改查中充当主键,它可以使任意字符串,在HBase内部RowKey保存为字节数组。
HBase中的数据是按照RowKey的ASCII字典顺序进行全局排序的,因此在设计RowKey时,要利用排序存储的特性,将经常读取的行存储到一起,避免做全表扫描。


Rowkey设计原则

  • HBase由于其存储和读写的高性能,在OLAP及时分析中发挥重要作用,HBase的查询只能通过rowkey来查询(rowkey便表示唯 一 一 行记录)
  • rowkey设计的优劣直接影响读写性能。HBase中的数据是按照rowkey的ASCII字典书序来进行全局排序
  • HBase提出的设计原则主要有:长度原则,唯一原则,排序原则和散列原则。

 举例 :

假如有5个RowKey:”012“,"0","123","234","3",按ASCII字典排序后的结果为:"0", "012", "123", "234", "3”

Rowkey排序时会先对比连个Rowkey的第一个字节,结果相同;然后会对比第二个字节,依次类推
由于HBase是通过Rowkey查询的,一般Rowkey都会存一些比较关键的检索信息,查询时会根据查询方式进行数据存储格式的设计,应该避免做去全表查询

长度原则              

  • RowKey是一个二进制码流,可以是任意字符串,最大长度为64kb,实际应用中一般为10-100bytes,以byte[]形式保存,一般设计成定长,建议越短越好,不要超过十六个字节,原因是:
  • 在 HBase 的底层存储 HFile 中,RowKey 是 KeyValue 结构中的一个域。假设 RowKey 长度 100B,那么 1000 万条数据中,光 RowKey 就占用掉 100*1000w=10亿个字节 将近 1G 空间,这样会极大影响 HFile 的存储效率。
  •  
  •  HBase 中设计有 MemStore 和 BlockCache,分别对应列族/Store 级别的写入缓存,和 RegionServer 级别的读取缓存。如果 RowKey 字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。
  • 此外,目前使用的基于64位的操作系统,内存是按照8B对齐的,所以设计RowKey时一般做成8B的整数倍,如16B或者24B,可以提高寻址效率。
  • 同样,列族、列名的命名在保证可读的情况下也应尽量短。value 永远和它的 key 一起传输的。当具体的值在系统间传输时,它的 RowKey,列名,时间戳也会一起传输(因此实际上列族命名几乎都用一个字母,比如‘c’或‘f’)。如果RowKey和列名和值相比较较大,Hfile中的索引最终占据了HBase分配的大量内存。
     

唯一原则

  • 由于RowKey用来唯一标识一行记录,所以必须在设计上保证RowKey的唯一性。
  • 由于 HBase 中数据存储的格式是 Key-Value 对格式,所以如果向 HBase 中同一张表插入相同 RowKey 的数据,则原先存在的数据会被新的数据给覆盖掉(和 HashMap 效果相同)。

排序原则 

  • RowKey是按照字典顺序排序存储的,所以设计RowKey时,利用排序特性,将经常读取的数据存储到一起,将最近可能访问的数据放到一起。
  • 一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为 RowKey 的一部分对这个问题十分有用,可以用 Long.Max_Value-timestamp追加到key的末尾。
  • 例如 [key][reverse_timestamp] , [key]的最新值可以通过scan [key]获得[key]的第一条记录,因为 HBase 中 RowKey 是有序的,第一条记录是最后录入的数据。

散列原则 

  • 散列原则就是设计出来的RowKey需要能均匀的分布到各个RegionServer上。
  • 比如设计RowKey时,当RowKey是按时间戳的方式递增,就不要将时间放在二进制码的前面,可以将RowKey的高位作为散列字段,由程序循环生成,可以在低位放时间字段,这样就可以提高数据均衡分布在每个RegionServer实现负载均衡的几率。
  • 如果没有散列字段,首字段只有时间信息,那就会出现所有新数据都在一个 RegionServer 上堆积的热点现象,这样在做数据检索的时候负载将会集中在个别 RegionServer 上,降低查询效率。

 

数据热点问题

  • 不合理的RowKey设计产生热点问题,热点发生在大量的client直接访问集中在个别RegionServer上(访问可能是读,写或者其他操作),导致单个RegionServer机器自身负载过高,引起性能下降

  • 大量的访问使热点region所在的单个机器超出自身承受能力,引起性能下降甚至导致region不可用,也将影响到同一个RegionServer上的其他region,由于主机无法服务其他region请求,就造成数据热点的现象。
  • 所以在向HBase中插入数据时,应该优化RowKey的设计,使数据被写入集群的多个region中,尽量将记录均衡的分散到不同的region中,平衡每个region的压力。

 解决数据热点问题的方法 

  • 主要的方法有反转,加盐和哈希
解决办法solution:
	 1、reverse反转
 例子:手机号反转后的字符串作为rowkey,这样避免了以手机号开头比较固定引起的热点问题 (如152、185等),但后半部分变化很多 如果将它反转过来,可以有效地避免热点
	缺点:牺牲了rowkey的有序性

     反转时间这个操作严格来讲不算“打散”,但可以调整数据的时间排序。如果将时间按照字典序排列,最近产生的数据会排在旧数据后面。如果用一个大值减去时间(比如用99999999减去yyyyMMdd,或者Long.MAX_VALUE减去时间戳),最新的数据就可以排在前面了。

	2、salt加盐
 在RowKey前添加一些前缀,加盐的前缀种类越多,RowKey被打的越散。
 比如在一个有4个Region的HBase表中,加salt前的rowkey:abc001,abc002,abc003,分别加上a、b、c前缀后的rowkey为a-abc001、b-abc002、c-abc003;可以看到,salting前数据分布在两个rowkey里,salting后数据分布在三个rowkey钟,避免热点现象 ,增加了读写的吞吐量 
 缺点:增加了读写开销
	
	3.Hash散列或者Mod
	例子:将上述的rowkey经过hash处理,采用md5散列算法取前4位做前缀
	结果:
9bf0-abc001 (abc001在md5后是9bf049097142c168c38a94c626eddf3d,取前4位是9bf0)
7006-abc002
95e6-abc003
上面几个rowkey数据会分布在3个region中,实际应用场景中,这种设计会使得分区之间更加均衡

总结 

  •  在做Rowkey设计时,请先考虑业务是读比写多、还是读比写少,HBase本身是为写优化的,即便是这样,也可能会出现热点问题,而如 果我们读比较多的话,除了考虑以上Rowkey设计原则外,还可以考虑HBase的Coprocessor甚至elastic search结合的方法,无论哪种方 式,都建议做实际业务场景下数据的压力测试以得到最优结果。
     
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值