HBase 热点问题——rowkey散列和预分区设计
作者:互联网
预分区背景
HBase默认建表时有一个region,这个region的rowkey是没有边界的,即没有startkey和endkey,在数据写入时,所有数据都会写入这个默认的region,随着数据量的不断增加,此region已经不能承受不断增长的数据量,会进行split,分成2个region。
在此过程中,会产生两个问题:
- 数据往一个region上写,会有写热点问题。造成单机负载压力大,影响业务的正常读写。
- 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算法。
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来恢复数据。
标签:前缀,region,xFF,split,rowkey,HBase,散列,分区 来源: https://blog.csdn.net/qq_26857259/article/details/122702800