hbase_性能调优

一、hbase性能调优

1. Hbase UI

默认为:http://IP:16010

可以在hbase-site.xml中配置端口

<property>

<name>hbase.master.info.port</name>

<value>60010</value>

</property>

hbase状态页面:http://ip:60010

页面中可以查看有哪些表,多少region

 

2. 单个region大小

默认为10G,建议5-10G。有的文章说默认是64M(应该是他们搞错了,hadoop1.0中的默认存储单元才是64M)

最直接的证据就是可以在hbase UI中查看:

 hbase_性能调优

<property>

<name>hbase.hregion.max.filesize</name>

<value>10737418240</value>

<source>hbase-default.xml</source>

</property>

 

创建表时可指定BLOCKSIZE参数。

块大小是HBase的一个重要配置选项,默认块大小为64M。对于不同的业务数据,块大小的合理设置对读写性能有很大的影响。而对块大小的调整,主要取决于两点:

 

1. 用户平均读取数据的大小。理论上讲,如果用户平均读取数据的大小较小,建议将块大小设置较小,这样可以使得内存可以缓存更多block,读性能自然会更好。相反,建议将块大小设置较大。

 

“下面这段比较来自网络,当时做笔记时忘了记出处”。

为了更好说明上述原理,笔者使用YCSB做了一个测试,分别在GetScan两种场景下测试不同BlockSize大小(16K64K128K)对性能的影响。测试结果分别如下面两图:

 hbase_性能调优

随着BlockSize的增大,系统随机读的吞吐量不断降低,延迟不断增大。64K大小比16K大小的吞吐量大约降低13%,延迟增大13%。同样的,128K大小比64K大小的吞吐量降低约22%,延迟增大27%。因此,对于以随机读为主的业务,可以适当调低BlockSize的大小,以获得更好的读性能。

 hbase_性能调优

随着BlockSize增大,scan的吞吐量逐渐增大,延迟不断降低。64K大小BlockSize16K大小的吞吐量增加了33%,延迟降低了24%128K大小比64K大小吞吐量增加了7%,延迟降低了7%;因此,对于以scan为主的业务,可以适当增大BlockSize的大小,以获得更好的读性能。

 hbase_性能调优

可见,如果业务请求Get请求为主,可以考虑将块大小设置较小;如果Scan请求为主,可以将块大小调大;默认的64K块大小是在ScanGet之间取得的一个平衡。

理解一下:如果块小,每次获取时快,响应快。但如果是想批量获取,一次获取太少反而慢。

选择较小块的大小的目的是使随机读取更快,而付出的代价是块索引变大,会消耗更多的内存。相反,如果平均键值对规模很大,或者磁盘速度慢造成了性能瓶颈,那就应该选择一个较大的块大小,以便使一次磁盘IO能够读取更多的数据

 

创建表时如何设置为此值为128M,报错:

ERROR: org.apache.hadoop.hbase.DoNotRetryIOException: Block size for column family prop  must be between 1K and 16MB. Set hbase.table.sanity.checks to false at conf or table descriptor if you want to bypass sanity checks

提示只能1K16M,或者设置配置不检查。在hbase-site.xml中添加如下配置即可:

<property>  

   <name>hbase.table.sanity.checks</name>  

   <value>false</value>  

</property>  

 

3. 每个regionserverregion数量

一般情况下,一个regionserver管理20-200region比较合理。

通常每个RS最大regions数目决定于memstore memory的使用情况,一个regionmemstore数量等于列族数,memstore大小默认128M

<property>

<name>hbase.hregion.memstore.flush.size</name>

<value>134217728</value>

<source>hbase-default.xml</source>

</property>

参考公式:

((RS memory) * (total memstore fraction)) / ((memstore size)*(# column families))

如机器有8G内存,每个表只有一个列族

8G*0.4/128M=25

如果你的regions只有一部分处于活跃写的状态,你可以调大regions数。即使是所有的regions都在写入,所有的region memstores也不会填满,由于有并发flush数目的限制。这样我们可以设置2~3regions数量作为起始点,然而增加regions也就意味找增加风险。

因此:一个8G内存的机器 ,放50个左右的region正常。

 

4. RegionServer Handler数量

通过hbase.regionserver.handler.count可以设置每台regionserver handler的数量,表示一个regionServer可以同时处理多少请求的线程数。默认10.

如果单次请求内存消耗低,TPS要求非常高的场景,可以调高此值。设置为10的位数,一般230倍属于正常。

 

5. Region核心切分流程

HBase将整个切分过程包装成了一个事务,意图能够保证切分事务的原子性。整个分裂事务过程分为三个阶段:prepare – execute – (rollback) ,操作模版如下:

 hbase_性能调优

prepare阶段:在内存中初始化两个子region,具体是生成两个HRegionInfo对象,包含tableNameregionNamestartkeyendkey等。同时会生成一个transaction journal,这个对象用来记录切分的进展,具体见rollback阶段。

execute阶段:切分的核心操作。见下图(来自 Hortonworks ):

hbase_性能调优

1) regionserver 更改ZK节点 /region-in-transition 中该region的状态为SPLITING

2) master通过watch节点/region-in-transition检测到region状态改变,并修改内存中region的状态,在master页面RIT模块就可以看到region执行split的状态信息。

3) 在父存储目录下新建临时文件夹.split保存split后的daughter region信息。

4) 关闭parent regionparent region关闭数据写入并触发flush操作,将写入region的数据全部持久化到磁盘。此后短时间内客户端落在父region上的请求都会抛出异常NotServingRegionException

5) 核心分裂步骤:在.split文件夹下新建两个子文件夹,称之为daughter Adaughter B,并在文件夹中生成reference文件,分别指向父region中对应文件。这个步骤是所有步骤中最核心的一个环节,生成reference文件日志如下所示:

2017-08-12 11:53:38,158 DEBUG [StoreOpener-0155388346c3c919d3f05d7188e885e0-1] regionserver.StoreFileInfo: reference 'hdfs://hdfscluster/hbase-rsgroup/data/default/music/0155388346c3c919d3f05d7188e885e0/cf/d24415c4fb44427b8f698143e5c4d9dc.00bb6239169411e4d0ecb6ddfdbacf66' to region=00bb6239169411e4d0ecb6ddfdbacf66 hfile=d24415c4fb44427b8f698143e5c4d9dc。

其中reference文件名为d24415c4fb44427b8f698143e5c4d9dc.00bb6239169411e4d0ecb6ddfdbacf66,格式看起来比较特殊,那这种文件名具体什么含义呢?那来看看该reference文件指向的父region文件,根据日志可以看到,切分的父region是00bb6239169411e4d0ecb6ddfdbacf66,对应的切分文件是d24415c4fb44427b8f698143e5c4d9dc,可见reference文件名是个信息量很大的命名方式,如下所示:

 hbase_性能调优

除此之外,还需要关注reference文件的文件内容,reference文件是一个引用文件(并非linux链接文件),文件内容很显然不是用户数据。文件内容其实非常简单,主要有两部分构成:其一是切分点 splitkey,其二是一个boolean类型的变量(true或者false),true表示该reference文件引用的是父文件的上半部分(top),而false表示引用的是下半部分 (bottom)。为什么存储的是这两部分内容?且听下文分解。

看官可以使用hadoop命令 亲自来查看reference文件的具体内容:

hadoop dfs -cat /hbase-rsgroup/data/default/music/0155388346c3c919d3f05d7188e885e0/cf/d24415c4fb44427b8f698143e5c4d9dc.00bb6239169411e4d0ecb6ddfdbacf66

6. region分裂为两个子region后, 将daughter Adaughter B拷贝到HBase根目录下,形成两个新的region

7. parent region通知修改 hbase.meta 表后下线,不再提供服务。下线后parent regionmeta表中的信息并不会马上删除,而是标注split列、offline列为true,并记录两个子region

 hbase_性能调优

8. 开启daughter Adaughter B两个子region。通知修改 hbase.meta 表,正式对外提供服务。

 hbase_性能调优