HBase求生之路-----HBase优化(一)

HBase求生之路(优化篇)

在这里插入图片描述


热点问题

什么叫热点问题,什么叫预分区?什么叫RowKey设计?三里屯VIP带你慢慢了解三个问号小朋友。

什么叫做预分区?大家都知道我Hbase建立一张表,会有一个Region,有这么一个分区的概念,正常情况下,我们的Region是不是会随着数据量的增长,会进行分裂Split,它这个分裂是不是自动分裂的,最开始只有一个,后来才会逐渐变成多个Region,它自己去分裂,其实是有一些不好的地方,哪些地方不好?

第一点:最开始我只有一个Region,那么我的读写请求都要发往这一个Region,虽然我们HBase是一个分布式NOSQL数据库,但是你只有一个Region的时候和分布式没多大关系,你的读写请求还是发往一个Region的,我支持的吞吐量差一些,毕竟只有一个Region,我如果采用自动分裂的话,我在分裂的时候不会那么及时的分裂的,只有等到这个Region达到一定的大小之后,才会进行分裂,说白了,我经过一定的时间,我才会有多个Region,我们的表,在很长一段时间内,我们的Region的个数,会很少,我读写的并发量上不去,尤其是我们自动分裂里面的达到默认大小固定十个G,当1个region中的某个Store下所有StoreFile的总大小超过hbase.hregion.max.filesize,该Region就会进行拆分(0.94版本之前),也就是说,我要等一个Region中的Store大小达到10个G,它才会分裂,很长一段时间,只会有很少的一些Region,分裂的很慢。这样会导致我们的并发量上不去。 而且,我们Region分裂的时候,产生新的Region的时候,我们的RowKey范围是我们控制不了的,人家自己选择一个RowKey范围,然后就分裂了,这样有什么不好呢?我们分裂完毕之后会请求新的Region,和老的Region没什么事了,但是我们自动分裂的不好就会导致,只往一个Region中,我们就会出现某一个Region负载过重,这就会很容易出现我们的Region热点问题。俗称:数据倾斜。

什么时候会出现热点问题?比如说我们的RowKey,RowKey是我们自己设置的,我们在工作的时候,可能会有这种业务需求,或者要求,需要将时间戳作为我们的RowKey,因为后续可能会需要我们的时间过滤我们的数据,我们假设就以时间戳作为RowKey,建表的时候也没有预分区,普通建表,一个分区,我这个数据往这个Region中写的时候,是不是都往这个Region中去写?随着时间增长,它分裂了,它一个Region分裂成了两个Region。

在这里插入图片描述
上图两个Region,RowKey范围已经划分,第一个0到20,第二个20到40,我们再写数据的时候会往哪里去写?因为我们是时间戳作为RowKey,拿肯定时间戳越来越大,就会都往第二个里面去写,然后第二个也越来越大了,又分裂了。然后又变成两个,然后又向它的第二个里面去写,然后又分裂,这就是很典型的Region热点问题。

预分区


所谓预分区,就是在们建立表的时候指明,我们这张表要有几个分区。每个分区,它的RowKey范围是什么?这个就是所谓的预分区,创建预分区表又几种方式呢?


第一种:手动设定预分区

create+表名+列族+第二个列族(可加可不加看自己)+SPLITS+箭头+数组。

启动Hadoop集群、zk集群,然后输入以下命令。 [fxy@hadoop101 hbase]$ bin/start-hbase.sh [fxy@hadoop101 hbase]$ bin/hbase shell hbase> create '表名','列族',SPLITS => ['1000','2000','3000','4000']
create 'partition','info',SPLITS => ['1000','2000','3000','4000']

在这里插入图片描述

数组相当于分区键,四个值会分成五个区。从负无穷到1000,1000到2000,2000到3000,3000到4000,4000到正无穷。

在这里插入图片描述

我们建立完之后,应该有五个分区才对。

我们打开HBase的Master的界面,我们看一下,我们可以简单的看一下每个分区的情况,我们可以在页面中观察的到。

在这里插入图片描述
往下拉,我们会看到Tables中的User Tables。还告诉我们Online Regions在线的分区有五个。

在这里插入图片描述
我们点进去看一下五个分区长什么样子。点击partition。点击Table Regions。会发现有五个分区。

在这里插入图片描述

前面的Name是一个Region的名字,一个随机的字符串,后面有Start Key与 End Key。其实这里的信息就相当于我们meta表中的信息了。


第二种:16进制序列预分区

我指明分区的个数NUMREGIONS => 15,分区键自己指定 SPLITALGO => ‘HexStringSplit’,SPLITALGO代表的是生成分区键的算法是什么,后面的Hex十六进制,意思是十六进制字符串作为我们的分区键。

create 'partition2','info',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}

在这里插入图片描述
我们到HBase中走一波,然后看一下效果。

在这里插入图片描述
在这里插入图片描述

我们点进去,看一下partition的Tables什么样子。

在这里插入图片描述

分区键全是十六进制的形式。这里相当于每个分区都是一个八位的十六进制,那我们的RowKey会是什么样子呢?八位16进制数最大就是八个f,我现在是15个分区,15个分区再16进制里除以f就可以了,我们还会发现八个3那个分区减去八个2,等于八个1,八个4减去八个3也是八个1,我们每个分区比前一个都多八个1,如果分成十个分区我们除以10就好了,那个就得自己去算了。八个f除以f等于八个1,就是这么来的

假设我们,有一个abc这样的RowKey,那么它会进入到哪个分区(哪个Region)?很显然它会进入到下面这个Region中。

在这里插入图片描述

但是我们能让它进入到这个Region么?答案是不能!如果我们今天以十六进制字符串为分区键的话,那么我们今天就不能让RowKey以字符串的形式存在了。假设我今天abc了,那我还会有什么f开头的,z开头的,那么这些都比e要大,那么这些数据都会进入到最后一个分区,又数据倾斜了。很显然我们不能以普通字符串为RowKey了。

那么假设我的RowKey就想用abc,我怎么处理以下比较合适呢?我应该将abc转成16进制。
怎么转?

Bytes.toHex(Bytes.toBytes("abc")) 可以试一道,代码复制粘贴即可 输出结果:616263 61就是a 62是b 63是c

结论:如果采用16进制分区,那么RowKey也要搞成16进制字符串


第三种:文件设置预分区

关闭HBaseShell客户端窗口。

这个骚操作就相当于把分区键写道文件当中了。

首先我们准备一个文件在集群上。

[fxy@hadoop101 hbase]$ vim split.txt

在这里插入图片描述
我们写这个分区键的时候,我们的分区键顺序有没有什么要求?没有要求,HBase很聪明,它会自己排序的。

我们启动Hbase Shell的时候也要在当前路径!!!
我们启动Hbase Shell的时候也要在当前路径!!!
我们启动Hbase Shell的时候也要在当前路径!!!

[fxy@hadoop101 hbase]$ bin/hbase shell
hbase(main):003:0> create 'partition3','info',SPLITS_FILE => 'split.txt'

在这里插入图片描述
在这里插入图片描述
我们去看一下WEB页面,看一下partition3中的分区情况。

在这里插入图片描述
点进去看一下。

在这里插入图片描述

使用JAVA的API创建预分区表
//自定义算法,产生一系列Hash散列值存储在二维数组中 byte[][] splitKeys = 某个散列值函数 //创建HbaseAdmin实例 HBaseAdmin hAdmin = new HBaseAdmin(HbaseConfiguration.create()); //创建HTableDescriptor实例 HTableDescriptor tableDesc = new HTableDescriptor(tableName); //通过HTableDescriptor实例和散列值二维数组创建带有预分区的Hbase表 hAdmin.createTable(tableDesc, splitKeys);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章