HBase Rowkey散列和预分区设计

预分区背景

HBase默认建表时有一个region,这个region的rowkey是没有边界的,即没有startkey和endkey,在数据写入时,所有数据都会写入这个默认的region,随着数据量的不断增加,此region已经不能承受不断增长的数据量,会进行split,分成2个region。

在此过程中,会产生两个问题:

  1. 数据往一个region上写,会有写热点问题。造成单机负载压力大,影响业务的正常读写。
  2. region split会消耗宝贵的集群I/O资源。

基于此我们可以控制在建表的时候,创建多个空region,并确定每个region的起始和终止rowky,这样只要我们的rowkey设计能均匀的命中各个region,就不会存在写热点问题。自然split的几率也会大大降低。当然随着数据量的不断增长,该split的还是要进行split。像这样预先创建hbase表分区的方式,称之为 预分区

热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region,由于主机无法服务其他region的请求,造成资源浪费。设计良好的数据访问模式以使集群被充分,均衡的利用。

数据倾斜:Hbase可以被划分为多个Region,但是默认创建时只有一个Region分布在集群的一个节点上,数据一开始时都集中在这个Region,也就是集中在这一个节点上,就算region存储达到临界值时被划分,数据也是存储在少数节点上。这就是数据倾斜

随机散列与预分区二者结合起来,是比较完美的。预分区一开始就预建好了一部分region,这些region都维护着自己的start-end keys,在配合上随机散列,写数据能均衡的命中这些预建的region,就能解决上面的那些缺点,大大提供性能。

1. 固定散列值

如果对rowkey加前缀盐处理,可以选择固定前缀预分区,分区规则如

  • a , b , c , d
  • 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9

这里所说的加盐不是 密码学中的加盐 ,而是在 rowkey 的前面增加随机数,具体就是给 rowkey 分配一个随机前缀以使得它和之前的 rowkey 的开头不同。分配的前缀种类数量应该 和你想使用数据分散到不同的 region 的数量一致。加盐之后的 rowkey 就会根据随机生成的 前缀分散到各个 region 上,以避免热点。

create 'user1',{NAME=>'f'},{NAME=>'d'},SPLITS=>['0|','1|','3|','4|','5|','6|','7|','8|','9|']

固定值散列,后面添加"|",因为|编码值最大

2. HexStringSplit(ASCII码预拆分策略)

Hbase 自带了两种 pre-split 的算法,分别是 HexStringSplit 和 UniformSplit 。HexStringSplit 适用于十六进制字符的 Rowkey(MD5)。UniformSplit 适用于随机字节组成的 Rowkey(Hash)。

如果我们的row key是 十六进制的字符串 作为前缀的,称之为HexStringSplit就比较适合用HexStringSplit,作为pre-split的算法。例如,我们使用HexHash(prefix)作为row key的前缀,其中Hexhash为最终得到十六进制字符串的hash算法,我们通常手动指定SPLITS来指定预分区,我们也可以用我们自己的split算法。

只需要传入一个要拆分的Region的数量,HexStringSplit会将数据 从起始到结束之间 的数据长度按照n等分之后算出每一段的起始rowkey和结束rowkey,以此作为拆分点。

  • 起始 00000000
  • 结束 FFFFFFFF
create 'test',{NAME=>'f',COMPRESSION=>'SNAPPY'},{NUMREGIONS => 30, SPLITALGO => 'HexStringSplit'}

3. UniformSplit(字节码预拆分策略)

只需要传入一个要拆分的Region的数量
与ASCII码预拆分不同的是,起始结束不是String而是 byte[]

  • 起始rowkey是 ArrayUtils.EMPTY_BYTE_ARRAY = new byte[0];
  • 结束rowkey是 new byte[]{xFF,xFF,xFF,xFF,xFF,xFF,xFF,xFF}

长度n等分,然后取每一段的起始和结束作为拆分点

防止热点的有效措施

哈希
 
哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是 可以预测的。使用确定的哈希可以让客户端重构完整的 rowkey,可以使用 get 操作准确获取 某一个行数据

HBase 写入流程

  • 第1步:Client获取数据写入的Region所在的RegionServer
  • 第2步:请求写Hlog
  • 第3步:请求写MemStore

只有当写Hlog和写MemStore都成功了才算请求写入完成。MemStore后续会逐渐刷到HDFS中。Hlog存储在HDFS,当RegionServer出现异常,需要使用Hlog来恢复数据。

  • 14
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值