其实HBase还是比较灵活的,关键看你是否使用得当,以下主要列举一些读的优化。HBase在生产中往往会遇到Full GC、进程OOM、RIT问题、读取延迟较大等一些问题,使用更好的硬件往往可以解决一部分问题,但是还是需要使用的方式。

我们把优化分为:

客户端优化、服务端优化、平台优化(ApsaraDB for HBase)

客户端优化

get请求是否可以使用批量请求

这样可以成倍减小客户端与服务端的rpc次数,显著提高吞吐量。

 Result[] re= table.get(List<Get> gets)

大scan缓存是否设置合理

scan一次性需求从服务端返回大量的数据,客户端发起一次请求,服务端会分多批次返回客户端,这样的设计是避免一次性传输较多的数据给服务端及客户端有较大的压力。目前数据会加载到本地的缓存中,默认100条数据大小。一些大scan需要获取大量的数据,传输数百次甚至数万的rpc请求。我们建议可以适当放开缓存的大小。

scan.setCaching(int caching) //大scan可以设置为1000

请求指定列族或者列名

HBase是列族数据库,同一个列族的数据存储在一块,不同列族是分开的,为了减小IO,建议指定列族或者列名。

离线计算访问Hbase建议禁止缓存

当离线访问HBase时,往往就是一次性的读取,此时读取的数据没有必要存放在blockcache中,建议在读取时禁止缓存。

scan.setBlockCache(false)

服务端优化

请求是否均衡

读取的压力是否都在一台或者几台之中,在业务高峰期间可以查看下,可以到HBase管控平台查看HBase的UI。如果有明显的热点,一劳永逸的做法是重新设计rowkey,短期是把热点地域尝试拆分。

BlockCache是否合理

BlockCache作为读缓存,对于读的性能比较重要,如果读比较多,建议内存使用1:4的机器,比如:8cpu32g或者16pu64g的机器。当前可以调高BlockCache的数值,降低Memstore的数值。

在ApsaraDB for HBase控制台可以完成:hfile.block.cache.size改为0.5 ; hbase.regionserver.global.memstore.size 改为0.3;再重启。

HFile文件数目

因为读取需要频繁打开HFile,如果文件越多,IO次数就越多,读取的延迟就越高,此时需要定时做major compaction,如果晚上的业务压力不大,可以在晚上做major compaction。

Compaction是否消耗较多的系统资源

compaction主要是将HFile的小文件合并成大文件,提高后续业务的读性能,但是也会带来较大的资源消耗。Minor Compaction一般情况下不会带来大量的系统资源消耗,除非因为配置不合理。切勿在高峰期间做 major compaction。建议在业务低峰期做major compaction。

Bloomfilter设置是否合理

Bloomfilter主要用来在查询时,过滤HFile的,避免不需要的IO操作。Bloomfilter能提高读取的性能,一般情况下创建表,都会默认设置为:BLOOMFILTER =>‘ROW’

平台端优化

数据本地率是否太低?(平台已经优化)

Hbase 的HFile,在本地是否有文件,如果有文件可以用Short-Circuit Local Read,目前平台在重启、磁盘扩容时,都会自动拉回移动出去的地域,不降低数据本地率;另外定期做major compaction也有益于提高本地化率。

Short-Circuit Local Read (已经默认开启)

当前HDFS读取数据需要经过DataNode,开启Short-Circuit Local Read后,客户端可以直接读取本地数据。

Hedged Read (已经默认开启)

优先会通过Short-Circuit Local Read功能尝试本地读。但是在某些特殊情况下,有可能会出现因为磁盘问题或者网络问题引起的短时间本地读取失败,为了应对这类问题,开发出了Hedged Read。该机制基本工作原理为:客户端发起一个本地读,一旦一段时间之后还没有返回,客户端将会向其他DataNode发送相同数据的请求。哪一个请求先返回,另一个就会被丢弃。

关闭swap区(已经默认关闭)

swap是当物理内存不足时,拿出部分的硬盘空间当做swap使用,解决内存不足的情况。但是会有较大的延迟的问题,所以我们HBase平台默认关闭。 但是关闭swap导致anon-rss很高,page reclaim没办法reclaim足够的page,可能导致内核挂住,平台已经采取相关隔离措施避免此情况。