HBASE优化、维护相关

一、性能优化
1.、垃圾回收优化
由于master负载通常比较轻,所以一般考虑region服务器启动参数。写负载高的情况下,memstore在不同时期创建各种不同大小的对象。memstore会保存缓冲区中的数据直到超过hbase.hregion.memstore.flush.size(建表时可以针对每个表指定这个参数)配置的大小才会刷写(或者客户端调用flushCommitts),这种刷写导致jvm堆存在孔洞。新生代空间比较小,垃圾回收很迅速不会有太大问题,但是长时间缓存的数据在老年代中,一般老年代会占据很大堆空间,回收很耗时。一般在hbase-env.sh中配置HBASE_REGIONSERVER_OPTS来设置垃圾回收选项。新生代垃圾回收用并行机制:-XX:UseParNewGC,并行回收占用大量CPU,但是我们配置的新生代比较小,不然该回收机制导致java进程停顿可能超出zookeeper的会话超时设置,从而让master误以为region服务器挂掉了,而且较小设置会防止对象过早进入老年代进而产生孔洞。老年代用并发标记回收器:+XX:UseConcMarkSweepGC和-XX:CMSInitiatingOccupancyFraction=70,这种回收会异步执行垃圾回收而不停止java进程。70高于region服务器设置的60%堆占用率(20%块缓存和40%的memstore),这样可以保证队用完之前回收空间,也不会因为执行的太早而回收太频繁。 一个初始的尝试可以是:HABSE_REGIONSERVER_OPTS="-Xmx:8G -Xms:8G -Xmn:128M -XX:+UseparNewGC -XX:+UseConcMarkSweepGC -XX:CMSInititalingOccupancyFraction=70 -veros:gc -XX:PrintGCDetails -XX:+PrintGCTimeStamps -xloggc:$HABSE_HOME/LOGS/gc.log"

2、本地memstore分配缓冲区 HBASE0.90.x引入MSLAB(memstore local allocation buffer)来解决memstore扰动(刷写keyvalue到磁盘时大量创建和删除对象,导致老年代孔洞发生;如果没有足够连续空间分配,则会用使应用程序停顿的stop-the world回收器)问题。MSLAB从对中分配固定大小的堆空间,所以对象被释放时只会留下固定大小的孔洞,之后产生的对象会重新利用这些孔洞,从而推导致迟长时间停顿的垃圾回收(不能避免)。开启MSLAB的配置:hbase.hregion.memstore.mslab.enabled,设置每个固定大小块的配置:hbase.hregion.memstore.mslab.chuncksize:默认值是2M,需要根据KEYVALUE的大小进行调整。对于使用这种分配的keyvalue大小也是有限制的:hbase.heregion.memstore.mslab.max.allocation:默认256K,超过该大小的对象直接在堆中分配(这种keyvalue过多的话,很使jvm更早遇到堆内存停顿的问题)。

3、开启压缩 Hbase支持大量压缩算法,并且支持列族级别的压缩。没有特殊情况(存储的JPEG图像已经压缩过等),最好是开启压缩。原因是很多压缩算法压缩和解压缩速度远远超过磁盘存取速度,因此在节省磁盘空间的同时还能提高提高整体数据处理速度。常用压缩算法:GZIP、lzo、zippy/snappy。其中GZIP压缩率最高(13%),但是解压缩(118M/s)和压缩(21M/s)速度最慢。lzo和snappy压缩(135M/s+)和解压缩(400M/s+)速度块GZIP4至5倍,但是压缩比稍微逊色(20%左右)。因此推荐使用snappy和lzo,但是需要自己安装依赖库。测试压缩库是否安装好:./hbase/bin/hbase org.apache.hadoop.hbase.util.CompressionTest /user/hbase/test.gz gz .测试成功不一定会能正常使用,因为这些算法依赖本地库。所以为了在region服务器启动时检测到问题,可以在配置文件hbase-site.xml中加入hbase.regionserver.codecs属性(值设为snappy,lzo),这样如果压缩有什么问题会在服务器启动时报错。使用压缩的命令:alter table 'testtable',{ NAME=>'CF1',COMPRESSION => 'GZ' }.

4、优化拆分和合并
region增大到一定程度后会拆分成两个,可能出现的问题是‘拆分/合并风暴’(通过关闭自动合并、拆分功能完成),同时也可能出现region热点问题即新写入的数据集中在一个region上(通过预分区和hashkey解决),或者出现表热点问题即一张表的大多数region分布在一台机器上导致这台机器承受写热点(通过move移动一个region到其他机器上)。 禁止自动拆分需要配置hbase.hregion.max.filesize为较大的值,如100G。 [code="java"] hbase.hregion.max.filesize 536870912000  Region管理: 移动region # 语法:move 'encodeRegionName', 'ServerName' # encodeRegionName指的regioName后面的编码,ServerName指的是master-status的Region Servers列表 # 示例 hbase(main)>move '4343995a58be8e5bbc739af1e91cd72d', 'db-41.xxx.xxx.org,60020,1390274516739' 手动split # 语法:split 'regionName', 'splitKey' major compaction 的功能是将所有的store file合并成一个,触发major compaction的可能条件有:major_compact 命令、majorCompact() API、region server自动运行(相关参数:hbase.hregion.majoucompaction 默认为24 小时、hbase.hregion.majorcompaction.jetter 默认值为0.2 防止region server 在同一时间进行major compaction)。hbase.hregion.majorcompaction.jetter参数的作用是:对参数hbase.hregion.majoucompaction 规定的值起到浮动的作用,假如两个参数都为默认值24和0,2,那么major compact最终使用的数值为:19.2~28.8 这个范围。.禁止自动合并(major compaction)需要配置参数hbase.hregion.majorcompaction=0,即 hbase.hregion.majorcompaction 0 shell 中major compact命令:major_compact 'testtable' minor compaction的运行机制要复杂一些,它由一下几个参数共同决定: hbase.hstore.compaction.min :默认值为 3,表示至少需要三个满足条件的store file时,minor compaction才会启动。hbase.hstore.compaction.max 默认值为10,表示一次minor compaction中最多选取10个store file。hbase.hstore.compaction.min.size 表示文件大小小于该值的store file 一定会加入minor compaction的store file中。hbase.hstore.compaction.max.size 表示文件大小大于该值的store file 一定会被minor compaction排除。hbase.hstore.compaction.ratio 将store file 按照文件年龄排序(older to younger),minor compaction总是从older store file开始选择,如果该文件的size 小于它后面hbase.hstore.compaction.max 个store file size 之和乘以 该ratio,则该store file 也将加入到minor compaction 中。 禁掉major_compaction和split后理论上写入应该无障碍了,但在测试中发现写入单个region速度大于10M/s时还是会出现长时间无法写入的情况。通过查看log,我们发现了这行log“Waited 90314ms on a compaction to clean up 'too many store files'”,通过查看代码发现原来是blockingStoreFiles这个参数在作怪。在flushRegion时会检测当前store中hfile的数量是否大于此值,如果大于则会block数据的写入,等待其他线程将hfile compact掉。这样,如果写入速度超过compact的速度,hbase就会阻止该region的数据写入。 我们将此值设为很大的值,使得此问题不会block我们的写入。 hbase.hstore.blockingStoreFiles 2100000000

5.负载均衡 在shell中执行:balance_switch true或者balance_switch flase,配置master是否执行平衡各个regionserver的region数量,当我们需要维护或者重启一个regionserver时,会 关闭balancer,这样就使得region在regionserver上的分布不均,这个时候需要手工的开启balance。默认情况下,均衡器每隔5分钟运行一次,每次运行间隔周期的一半即2分半钟,分别由参数hbase.balancer.period属性和hbase.balancer.max.balancing设置。在手动控制均衡器的同时,应该根据表的region分布进行move操作手动移动region。

6.合并region 上文的合并(compact)是合并同一个region里面的多个文件,去除同一rowkey下的过期版本。这里的合并是把相邻的region合并为一个。合并的原因可能是表执行了大量的删除操作导致每个region的数据量较少,同时为了减少每个region服务器的region数量。 命令行shell中操作的步骤:首先,执行scan ‘。meta.’,{COLUMNS => ['info:regioninfo']}得到目标表的region列表;然后,./bin/hbase org.apache.hadoop.hbase.util.merge testtable regionName1 regiionName2.

7.客户端API
1)禁止自动刷写
当有大量的写入操作时,使用setAutoFlush(false)方法,这样各个put就会先缓存在客户端直到缓冲区满或者调用flushCommits().当然htable的close方法也会隐式调用flushCommits方法。 2)使用扫描缓存 当HBASE被用作mapreduce作业的输入源,一定要调用scanner的setCaching(XX),且XX的值最好设置的比较大,如500.这样可以阻止每一条记录都要请求region服务器。当然,要权衡内存占用和请求开销。
3)限定扫描范围 尤其是在HBASE被用作输入源时,注意作业需要的是那些列,只将用到的列加入scan输入中。
4)关闭resultScanner
这不会带来性能提升,但是可以避免对服务器造成性能影响。
5)块缓存
scan方法的setCacheBlocks(boolean)用来设置是否使用服务器端的块缓存。开关原则:如果是mapreduce作业,那就关闭啦吧,如果是经常重复访问的热点数据,那就开启。注意这个值默认是开启。
6)优化获取行健的方式
如果某个查询只需要获取行健,不要列族,列名,列值和时间戳。Scan中添加一个带MUST_PASS_ALL的filterlist。list中包含firstKeyFilter和keyOnlyFilter两个过滤器,这样就只返回第一个keyvalue的行健,减少网络开销。
7)关闭PUT的WAL
如果数据容忍丢失,在大批量写入数据时,可以调用put的writeToWAL(false)。当然关注高吞吐量时可以考虑bulk load技术。


8、配置方面
1)减少zookeeper超时的发生时间
zookeeper.session.timeout属性控制着region服务器失效的时间。默认3分钟,设置为更小的值可以让master更快发现故障的region服务器。此参数的配置一定要根据region服务器的jvm参数调整,防止垃圾回收时进程得不到执行时间而导致region服务器被误以为崩溃。

2)增加处理线程
hbase.regionserver.handler.count属性定义了region服务器响应外部用户访问数据请求的线程数,默认值10是比较小的。较小的值有利于单词请求涉及的数据量较大的场景,如几兆,单次请求的数据量较小的情况(put,get,delete)下适合设置较大的线程数。例如若集群服务于一个网站时,客户端大多数时候都是当个的put和get操作,此时为提高并发量,应该设置较大的数字。
3)增加堆大小
hbase默认使用的都是保守和稳妥的配置。如果服务器性能较高,hbase-env.sh配置堆得大小为8G以上也是合理的。 4)开启压缩 配置文件中在没有特殊情况下都开启压缩,推荐snappy和lzo。
5)增加region大小
较少的region可以使服务器运行的更加稳定。如果region变热,可以手动拆分为两个。默认region大小为256M,实际可以配置至少G级别的。
6)调整快缓存的大小
堆中块缓存的大小用属性hfile.block.cache.size控制,默认为0.2.即块缓存占堆的20%(通常memstore配置为40%)。对于写少读多的表,有必要设置较大的快缓存。
7)调整memstore限制
配置一台regionserver所有memstore占整个堆的最大比例,默认是0.4/0.35,二个值的差异在于是做局部的flush,还是全部flush,如果你的regionserver日志中,频发出现因为超过 hbase.regionserver.global.memstore.lowerLimit而做flush的信息,我觉得有必要调小 hbase.hregion.memstore.flush.size,或者适当调大这二个值,当然 hbase.regionserver.global.memstore.upperLimit和hfile.block.cache.size的和不能大于1,到0.8我觉得已经够大了。如果你的jvm内存回收是使用cms的话,有一个值 CMSInitiatingOccupancyFraction(内存使用到时多少时,一始cms回收内存)的大小和觉得和这个有关系,略大于 hbase.regionserver.global.memstore.upperLimit和hfile.block.cache.size的和是一个不错的选择。当处理读多写少时,可以增加块缓存的值而调低memstore的值,反之亦然。
8)增加阻塞时存储文件数目
hbase.hstore.blockingStoreFiles来设置该值,默认为7。若存储文件的数目达到该值时,将阻塞更新操作。对于经常遇到大负载突发写入时,必须调高该值到上百。
9)增加阻塞倍率
hbase.hregion.memstore.block.multiplier的默认值为2.该值表示memstore的值超过multiplier乘以flush.size的积时,阻塞客户端的更新。如果region服务器有较大的内存空间,可以设置更大的值,来应对突发写。可以和8)一起使用。
10)WAL
WAL中包含了所有已经写入Memstore但还未Flush到HFile的更改(edits)。在Memstore中数据还没有持久化,当RegionSever宕掉的时候,可以使用WAL恢复数据。 当WAL(在HBase中成为HLog)变得很大的时候,在恢复的时候就需要很长的时间。因此,对WAL的大小也有一些限制,当达到这些限制的时候,就会触发Memstore的flush。Memstore flush会使WAL 减少,因为数据持久化之后(写入到HFile),就没有必要在WAL中再保存这些修改。有两个属性可以配置: hbase.regionserver.hlog.blocksize hbase.regionserver.maxlogs 你可能已经发现,WAL的最大值由hbase.regionserver.maxlogs * hbase.regionserver.hlog.blocksize (2GB by default)决定。一旦达到这个值,Memstore flush就会被触发。所以,当你增加Memstore的大小以及调整其他的Memstore的设置项时,你也需要去调整HLog的配置项。否则,WAL的大小限制可能会首先被触发,因而,你将利用不到其他专门为Memstore而设计的优化。抛开这些不说,通过WAL限制来触发Memstore的flush并非最佳方式,这样做可能会会一次flush很多Region,尽管“写数据”是很好的分布于整个集群,进而很有可能会引发flush“大风暴”。 提示:最好将hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs 设置为稍微大于hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE.

你可能感兴趣的:(hbase)