HBase的性能优化主要围绕提升HBase的读写性能围绕,包括Client端程序优化以及HBase服务端参数配置优化。其中,Client端可以从减少RPC调用次数入手,使用缓存,采用批量请求的方式。HBase服务端参数配置优化,又主要包括良好的RowKey设置保证负载均衡,良好的ColumnFamily设置,适当的MemStore Flush配置和Compaction配置以及合理的内存规划等方面。
1. 读性能优化
1.1 Client端
1.1.1 减少RPC请求次数
Client端查询程序开发时,针对Get请求,在Client端宕机时允许Get请求丢失一部分的情况下,可以采用批量Get请求的方式,减少RPC请求次数。针对Scan请求,默认会每次从HBase服务端拉取100条数据进行缓存,当Scan的数据量较大时,我们可以增大Caching的条数,每次从HBase服务端拉取1000条数据,从而减少RPC请求次数。
1.1.2 精确查询
HBase服务端在读取数据时会Client端的查询条件对表中的数据进行检索,因此Client端在读取数据时尽量指定RowKey或RowKey-Column精确查询,缩小HBase服务端的检索范围,从而提升读取性能。
1.1.3 大数据量Scan关闭缓存
Scan拉取的数据都会保存在Client端的本地缓存中,当数据量特别大,由于本地缓存较小,往往会将内存中的其他关键数据交换出去,影响Client端性能。因此针对每条数据仅仅使用一次的情况,我们可以关闭Scan的本地缓存。
1.2 服务端
1.2.1 负载均衡
HBase中若数据集中在几个甚至一个HRegionServer中,读取数据时,该HRegionServer负载会特别重,成为数据查询的单点性能瓶颈。良好的RowKey设计,可以保证数据均匀的分布在HBase集群中,负载均衡。因此读取数据时,HBase集群可以实现良好的分布式查询。
1.2.2 BloomFilter
每个ColumnFamily中都可以配置BloomFilter,分为None/Row/Row-Col三种,当BloomFilter开启时,查询数据的过程中可以利用BloomFilter快速的过滤掉不包含所需数据的HFile文件,可以大大提升读取速度。
1.2.3 BlockCache
BlockCache是读缓存,可以大幅提升读取性能。我们可以针对读多写少的应用场景,适当提高BlockCache的占比,降低MemStore的占比,从而进一步提升读取性能。
另一方面,由于BlockCahce中的数据需要根据数据热度,频繁交换,因此BlockCache的垃圾回收机制的配置也至关重要,对BlockCahce的影响较大,在BucketCache的offheap模式下GC表现很优越,建议使用。
1.2.4 Compaction配置
Compaction主要用来对HFile文件进行合并,保证Store下的HFile文件不至于过多,影响读取性能。Compaction分为Minor-Compaction和Major-Compaction。
- Minor Compaction是指选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile,在这个过程中不会处理已经Deleted或Expired的Cell。一次Minor Compaction的结果是更少并且更大的StoreFile。
- Major Compaction是指将所有的StoreFile合并成一个StoreFile,这个过程还会清理三类无意义数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。另外,一般情况下,Major Compaction时间会持续比较长,整个过程会消耗大量系统资源,对上层业务有比较大的影响。因此线上业务都会将关闭自动触发Major Compaction功能,改为手动在业务低峰期触发。
Compaction对HFile的合并主要通过两个参数来设置,hbase.hstore.compactionThreshold
表示一个store中的文件数超过多少就应该进行合并。hbase.hstore.compaction.max.size
表示参数合并的文件大小最大是多少,超过此大小的文件不能参与合并。hbase.hstore.compactionThreshold
设置不能太大,默认是3个;设置需要根据Region大小确定,通常可以简单的认为hbase.hstore.compaction.max.size = RegionSize / hbase.hstore.compactionThreshold
1.2.5 ColumnFamily 列簇设计
列簇设计优化也是HBase的读写性能优化点,包括列簇数量、BlockSize大小、BloomFilter设置、Compresssion等配置,都会对HBase的读写性能产生影响。1.2.6 HDFS优化
因为HBase是基于HDFS存储的,包含HLog和HFile都存储在HDFS上,因此有关HDFS上的一些配置也会影响HBase的性能。
2. 写性能优化
2.1 Client端
与读性能优化相同,写性能优化在Client端主要也是尽量减少Client与服务端的RPC通信次数。Client端的Put操作可以单挑写入,也可以通过List
需要注意的是,无论时读批量操作还是写批量操作,当Client端宕机时,都有丢失操作请求的风险。
2.2 服务端
2.2.1 关闭WAL
WAL机制下,写入HBase的数据首先会写入HLog进行持久化,然后才会写入MemStore。若部分业务允许HReionServer异常下可以丢失MemStore尚未溢出到HFile的数据,且更加注重HBase的写入性能,则我们可以考虑关闭WAL机制,使写入数据跳过HLog部分,直接写入MemStore,这种方式可以大幅提高HBase的写入性能。
2.2.2 负载均衡
与读性能优化小节中提到的相同,良好的RowKey设置,HBase集群良好的负载均衡,可以保证数据的写入性能。
另一方面,如果表的Region数量少于HBase集群中HRegionServer数量,将无法充分利用HBase的资源,无法充分进行分布式读写,因此我们可以通过预分区或对高负载Region进行切分等方式,使Region数量不少于HRegionServer数量。
2.2.3 MemStore配置
MemStore中的数据在溢出到HFile时以及Store对HFile文件进行Compaction操作时,HBase的写入性能会受到严重影响,因此MemStore中有关Flush和Compaction的参数对HBase的写入性能优化至关重要。
- 一旦整个RegionServer上所有Memstore占用内存大小总和大于配置文件中upperlimit时,系统就会执行RegionServer级别flush,flush算法会首先按照Region大小进行排序,再按照该顺序依次进行flush,直至总Memstore大小低至lowerlimit。这种flush通常会阻塞HRgionServer较长时间。如果RegionServer上Region较多,而Memstore总大小设置的很小(JVM设置较小或者upper.limit设置较小),就会触发HRegionServer级别flush。因此对于该参数需要合理配置。
hbase.hstore.blockingStoreFiles
该参数表示如果当前Store中文件数大于该值,系统将会强制执行Compaction操作进行文件合并,合并的过程会阻塞整个Store的写入。该参数一般建议设置为5~8左右。2.2.4 数据长度过长
当HBase的KeyValue保存的数据过长时,写入数据时会耗费较长时间,数据吞吐量也较低,这种情况下,由于HBase耗费很多的资源处理该业务的读写请求,其他业务的读写性能将受到严重影响,这是需要特别注意的一点。
ps: 参考文献及图片来源:有态度的HBase/Spark/BigData