一、HBase关键参数配置指导
如果同时存在读和写的操作,这两种操作的性能会相互影响。如果写入导致的flush和Compaction操作频繁发生,会占用大量的磁盘IO操作,从而影响读取的性能。如果写入导致阻塞较多的Compaction操作,就会出现Region中存在多个HFile的情况,从而影响读取的性能。所以如果读取的性能不理想的时候,也要考虑写入的配置是否合理。
1、提升写效率
1.1客户端调优
1.1.1 AutoFlush
参数值:setAutoFlush
解析:
autoflush=false的原理是当客户端提交delete或put请求时,将该请求在客户端缓存,直到数据超过2M(hbase.client.write.buffer决定)或用户执行了hbase.flushcommits()时才向regionserver提交请求。因此即使htable.pu()执行返回成功,也并非说明请求真的成功了。假如还没有达到该缓存而client崩溃,该部分数据将由于未发送到regionserver而丢失。这对于零容忍的在线服务是不可接受的。
autoflush=true虽然会让写入速度下降2-3本,但是对于很多在线应用来说这都是必须打开的,也正是hbase为什么让它默认为true的原因,每次请求都会发往regionserver,而regionserver接收到请求后第一件事情就是写HLOG。因此对IO要求是非常高的,为了提高hbase的写入速度应该尽可能地提高IO吞吐量,比如增加磁盘、使用raid卡、减少replication因子数等。
如何调优?
经验设定:
setAutoFlush=false
1.1.2使用PutList方式提交请求
可以极大地提升写性能
1.2 Memstore相关
当regionserver(以下简称为RS)收到一个写请求,会将这个请求定位到某个特定的region。每一个region存储了一系列的Row,每一个Row对应的数据分散在一个或多个ColumnFamily(以下简称为CF)。特定CF的数据都存储在对应的store里面,而每个store都是由一个memstore和数个storefile组成。memstore存储在RS的内存中,而storefile则存储在HDFS上。当一个写请求到达RS的时候,该请求对应的数据首先会被menstore存储,直到达到一定的临界条件,memstore里面的数据才会flush到storefile。
使用memstore的主要原因是为了使存储在HDFS上的数据是有序的(按Row)。HDFS设计为顺序读写的,已有的文件不能被修改。这就意味着,因为hbase收到的写请求是无序的,所以如果直接将这些数据写到HDFS上,以后再对文件里面的内二做排序就会是一件极其困难的事情;无序的数据存储方式,又会大大影响后续的读请求性能。为了解决这种问题,hbase会将最近的某些写请求放到内存中(也就是memstore),并将这些数据在flush到storefile之前做好排序。
除了解决排序的问题,memstore还有其他好处,比如:
它能充当memcache的角色,缓存最近写入的数据。鉴于新数据的访问频率和几率都比旧数据高很多,这就大大的提高客户端的读效率。
注意:每个memstore每次刷新时,都会给CF生产一个storefile。
剩下读取就非常容易了,hbase会检查数据是否在memstore里面,否则就去storefile读取,然后返回给客户端。
1.2.1 根据memstore大小flush hfile
参数值:hbase.hregion.memstore.flush.size
参数解析:
在regionserver中,当写操作内存中存在超过memstore.flush.size大小的memstore,则MemstoreFlusher就启动flush操作将该memstore以hfile的形式写入对应的store中。
如何调优?
默认:128M
A、如果Regionserver的内存充足,而且活跃Region数量也不是很多的时候,可以适当增大该值,可以减少compaction的次数,有助于提升系统性能。
B、这种flush产生的时候,并不是紧急的flush,flush操作可能会有一定延迟,在延迟期间,写操作还可以进行,Memstore还会继续增大,最大值 = “memstore.flush.size” * "hbase.hregion.memstore.block.multiplier"。
C、当超过最大值时,将会阻塞写操作。适当增大“hbase.hregion.memstore.block.multiplier”可以减少阻塞,减少性能波动。
参数值:hbase.regionserver.global.memstore.size
参数解析:
RegionServer中,负责flush操作的是MemStoreFlusher线程。该线程定期检查写操作内存,当写操作占用内存总量达到阈值,MemStoreFlusher将启动flush操作,按照从大到小的顺序,flush若干相对较大的memstore,直到所占用内存小于阈值。
阈值=“hbase.regionserver.global.memstore.size” * "hbase.regionserver.global.memstore,size.lower.limit" * "Hbase_HEAPSIZE"
如何调优?
默认:0.4
该配置与“hfile.block.cache.size”的和不能超过0.8,也就是写和读操作的内存不能超过HeapSize的80%,这样可以保证除读和写以外其他操作的正常运行。
1.2.3 Flush前进行Compaction
参数值:hbase.hstore.blockingStoreFiles
参数解析:
在region flush前首先判断file文件个数,是否大于hbase.hstore.blockingStoreFiles。如果大于需要先Compaction并且让flush延时90s(这个参数可以通过hbase.hstore.blockingWaitTime进行配置),在延时过程中,将会继续写从而使得Memstore还会继续增大超过阈值(“memstore.flush.size” * "hbase.hregion.memstore.block.multiplier"),导致写操作阻塞。当完成Compaction后,可能就会产生大量写入。这样就导致性能激烈震荡。
如何调优?
默认:7
增加hbase.hstore.blockingStoreFiles,可以降低Block几率。
1.3 内存相关