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中查看:
<property>
<name>hbase.hregion.max.filesize</name>
<value>10737418240</value>
<source>hbase-default.xml</source>
</property>
创建表时可指定BLOCKSIZE参数。
块大小是HBase的一个重要配置选项,默认块大小为64M。对于不同的业务数据,块大小的合理设置对读写性能有很大的影响。而对块大小的调整,主要取决于两点:
1. 用户平均读取数据的大小。理论上讲,如果用户平均读取数据的大小较小,建议将块大小设置较小,这样可以使得内存可以缓存更多block,读性能自然会更好。相反,建议将块大小设置较大。
“下面这段比较来自网络,当时做笔记时忘了记出处”。
为了更好说明上述原理,笔者使用YCSB做了一个测试,分别在Get、Scan两种场景下测试不同BlockSize大小(16K,64K,128K)对性能的影响。测试结果分别如下面两图:
随着BlockSize的增大,系统随机读的吞吐量不断降低,延迟不断增大。64K大小比16K大小的吞吐量大约降低13%,延迟增大13%。同样的,128K大小比64K大小的吞吐量降低约22%,延迟增大27%。因此,对于以随机读为主的业务,可以适当调低BlockSize的大小,以获得更好的读性能。
随着BlockSize增大,scan的吞吐量逐渐增大,延迟不断降低。64K大小BlockSize比16K大小的吞吐量增加了33%,延迟降低了24%;128K大小比64K大小吞吐量增加了7%,延迟降低了7%;因此,对于以scan为主的业务,可以适当增大BlockSize的大小,以获得更好的读性能。
可见,如果业务请求以Get请求为主,可以考虑将块大小设置较小;如果以Scan请求为主,可以将块大小调大;默认的64K块大小是在Scan和Get之间取得的一个平衡。
理解一下:如果块小,每次获取时快,响应快。但如果是想批量获取,一次获取太少反而慢。
选择较小块的大小的目的是使随机读取更快,而付出的代价是块索引变大,会消耗更多的内存。相反,如果平均键值对规模很大,或者磁盘速度慢造成了性能瓶颈,那就应该选择一个较大的块大小,以便使一次磁盘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
提示只能1K到16M,或者设置配置不检查。在hbase-site.xml中添加如下配置即可:
<property>
<name>hbase.table.sanity.checks</name>
<value>false</value>
</property>
3. 每个regionserver中region数量
一般情况下,一个regionserver管理20-200个region比较合理。
通常每个RS最大regions数目决定于memstore memory的使用情况,一个region的memstore数量等于列族数,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~3倍regions数量作为起始点,然而增加regions也就意味找增加风险。
因此:一个8G内存的机器 ,放50个左右的region正常。
4. RegionServer Handler数量
通过hbase.regionserver.handler.count可以设置每台regionserver handler的数量,表示一个regionServer可以同时处理多少请求的线程数。默认10.
如果单次请求内存消耗低,TPS要求非常高的场景,可以调高此值。设置为10的位数,一般2到30倍属于正常。
5. Region核心切分流程
HBase将整个切分过程包装成了一个事务,意图能够保证切分事务的原子性。整个分裂事务过程分为三个阶段:prepare – execute – (rollback) ,操作模版如下:
prepare阶段:在内存中初始化两个子region,具体是生成两个HRegionInfo对象,包含tableName、regionName、startkey、endkey等。同时会生成一个transaction journal,这个对象用来记录切分的进展,具体见rollback阶段。
execute阶段:切分的核心操作。见下图(来自 Hortonworks ):
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 region:parent region关闭数据写入并触发flush操作,将写入region的数据全部持久化到磁盘。此后短时间内客户端落在父region上的请求都会抛出异常NotServingRegionException。
5) 核心分裂步骤:在.split文件夹下新建两个子文件夹,称之为daughter A、daughter 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文件名是个信息量很大的命名方式,如下所示:
除此之外,还需要关注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 A、daughter B拷贝到HBase根目录下,形成两个新的region。
7. parent region通知修改 hbase.meta 表后下线,不再提供服务。下线后parent region在meta表中的信息并不会马上删除,而是标注split列、offline列为true,并记录两个子region。
8. 开启daughter A、daughter B两个子region。通知修改 hbase.meta 表,正式对外提供服务。