第13章 HBase 系统调优
13.1 HBase GC调优
todo
13.2 G1 GC性能调优
todo
13.3 HBase操作系统调优
todo
13.4 HBase—HDFS 调优策略
HDFS作为Hbase最终数据存储系统,对HDFS的相关优化也会影响HBase的读写性能。
这里主要关注一下三个方面
1.Shor-Circuit Local Read
当前HDFS 读取数据都需要经过DataNode,客户端会向DataNode发送读取数据请求,
DataNode接收到请求后从磁盘中将数据读出来,再通过TCP发送给客户端。
对本地数据,Shor Circuit Local Read策略允许客户端绕过DataNode 直接从磁盘上读取本地数据,
因为不需要经过DataNode而减少了多次网络传输开销,因此数据读取的效率更高。
开启 Shor Circuit Local Read功能,需要在Hbasesitexml或者hdf-site.xml配置文中增加如下配置项:
···
<property>
<name>dfs.client.read.shorteireuite</name>
<values>true</values>
</property>
<property>
<names>dfs.domain.socket.pathe</names>
<values>/home/stack/sockets/short-circuit_read_socket_PORFe</value>
</property>
<property>
<namesdfs.client.read.shorteircuit.buffer.sizec</names>
<values>131072</values>
</property>
</configuration>
···
需要注意的是,dfs.client.read.shortcircuit.buffer.size参数默认是1M,对于HBase系统来说有可能会造成OOM
2. Hedged Read
HBase数据在HDFS中默认存储三个副本,通常情况下HBase 会根据一定算法优先议择一个DataNode进行数据读取。
然而在某些情况下,有可能因为磁盘问题或者网络问题月引起读取超时,
根据Hedged Read策略,如果在指定时间内读取请求没有返回,HDFS名户端将会向第二个副本发送第二次数据请求,
并且谁先返回就使用谁,之后返回的将会创丢弃。
开启Hedged Read 功能,需要在hbase-site.xml 配置文件中增加如下配置项:
<property>
<name>dfs.client. hedged. read. threadpool.size</name>
<value>20</values> <!--20 threads -->
</property>
<property>
<name>dfs.client.hedged.read.threshold.millis</name>
<value>10</value> <!--10 milliseconds -->
</property>
其中,参数dfs.client.hedged. read.threadpool.size 表示用于 hedged read的线程池线程数量,
默认为0,表示关闭 hedged read功能;
参数ds.clien.hedged.read.threshold.milis表引HDFS数据读取超时时间,超过这个阈值,HDFS客户端将会再发起一次读取请求。
3. Region Data Locality
Region Data Locality,即数据本地率,表示当前Region 的数据在 Region 所在节点存例的比例。
数据本地率太低会数据读取时产生大量的跨网络IO,导致读请求延迟较高
13.5 HBase读取性能优化
13.5.1 HBase服务端优化
1.读请求是否均衡
优化原理:
假如业务所有读请求都落在集群某一台RegionSserver 上的其几个Regionn,
一方面不能发挥整个集群的并发处理能力,
另一方面势必造成此台RegionServer资源严重消耗(比如 IO耗尽、handler耗尽等),
导致落在该台RegionServer 上的其他业务受到波动
也就是说读请求不均衡不仅会造成本身业务性能很差,还会严重影响其他业务。
观察确认:
观察所有RegionServer的读请求OPS曲线,确认是否存在读请求不均衡现象。
优化建议:
Rowkey必须进行散列化处理(比如MD5散列),同时建表必须进行预分区|处理,
2.BlockCache 设置是否合理?
优化原理:
BlockCache作为读缓存,对于读性能至关重要。
默认情况下 BlockCache和MemStore的配置相对比较均衡(各占40%),
可以根据集群业务进行修正,比如读多写少业务可以将 BlockCache占比调大。
另一方面,BlockCache的策略选择也很重要,不同策略对读性能来说影响并不是很大,
但是对GC的影响却相当显著,尤其在 BucketCache的ofheap模式下 GC表现非常优秀
观察确认:
观察所有RegionServer的缓存未命中率、配置文件相关配置项以及GC日志,确认BlockCache 是否可以优化。
优化建议:
如果JVM内存配置量小于20G, BlockCache策略选择LRUBlocKCache;否则选择 BucketCache策略的offheap模式。
3. HFile 文件是否太多?
优化原理:
HBase在读取数据时通常先到MemStore 和 BlockCache中检索(读取最近写入数据和热点数据),
如果查找不到则到文件中检索。HBase的类LSM树结构导致每个 store包含多个HFile 文件,
文件越多,检索所需的IO次数越多,读取延迟也就越高。
文件数量通常取决于Compaction的执行策略,一般和两个配置参数有关:
hbase.hstore.compactionThreshold 和hbase.hstore.compaction.max.size,
前者表示一个 store中的文件数超过阀值就应该进行合并,
后者表示参与合并的文件大小最大是多少,超过此大小的文件不能参与合并。
这两个参数需要谨慎设置,如果前者设置太大,后者设置太小,就会导致 Compaction 合并文件的实际效果不明显,
很多文件得不到合并,进而导致HFile 文件数变多。
观察确认:
观察RegionServer级别以及Region级别的HFie数,确认HFile 文件是否过多。
优化建议:
hbase.hstorecompactiorThreshold设置不能太大,默认为3个。
4.Compaction 是否消耗系统资源过多?
优化原理:
Compaction是将小文件合并为大文件,提高后续业务随机读性能,
会带来1O放大以及带宽消耗问题(数据远程读取以及三副本写入都会消耗系带宽)
正常配置情况下,Minor Compaction 并不会带来很大的系统资源消耗,
除非因为配置不合理导致 Minor Compaction太过顺繁,或者Region 设置太大发生Major Compaction。
观察确认:
观察系统IO 资源以及带宽资源使用情况,再观察 Compaction 队列长确认是否由于Compaction导致系统资源消耗过多。
优化建议:
对于大Region 读延迟做感的业务(100G以上)通常不建议开启自动Major Compaction,手动低峰期触发。
小Region或者延迟不敏感的业务可以开启Major Compaction,但建议限流
5.数据本地率是不是很低?
优化原理:
13.4节详细介绍了HBase中数据本地率的概念,如果数据本地率很低。
据读取时会产生大量网络IO请求,导致读延迟较高。
观察确认:
观察所有RegionServer的数据本地率(见jmx中指标PercentFileLocal. Table Web UI可以看到各个Region的Locality)。
优化建议:
尽量避免Region无故迁移。对于本地率较低的节点,可以在业务低峰期执行major compact。
13.5.2 HBase 客户端优化
1.scan缓存是否设置合理?
优化原理:
HBase业务通常一次scan就会返回大量数据,因此客户端发起一次scan请求,
实际并不会一次就将所有数据加载到本地,而是分成多次RPC请求进行加载,
这样设计一方面因为大量数据请求可能会导致网络带宽严重消耗进而影响其他业务,
另一方面因为数据量太大可能导致本地客户端发生OOM。
在这样的设计体系下,用户会首先加载一部分数据到本地,然后遍历处理,
再加载下一部分数据到本地处理,如此往复,直至所有数据都加载完成。数据加载到本地就存放在scan缓存中,默认为100条数据。
通常情况下,默认的 scan缓存设置是可以正常工作的。但是对于一些大scan(一次scan可能需要查询几万甚至几十万行数据),
每次请求100条数据意味着一次scan需要几百甚至几千次RPC请求,这种交互的代价无疑是很大的。
因此可以考虑将 scan缓在设置增大,比如设为500或者1000条可能更加合适。
优化建议:
大scan场景下将scan缓存从100增大到500或者1000,用以减少RPC饮数。
2. get 是否使用批量请求?
优化原理:
HBase分别提供了单条 get以及批量 get的API接口,
使用批量 get接口可以减少客户端到RegionServer 之间的RPC连接数,提高读取吞吐量。
另外需要注意的是,批量请求要么成功返回所有请求数据,要么抛出异常。
加优化建议:
使用批量 get进行读取请求。需要注意的是,对读取延迟非常敏感的业务,批量请求时每次批量数不能太大,最好进行测试。
3.请求是否可以显式指定列族或者列?
优化原理:
HBase是典型的列族数据库,意味着同一列侯的数据存储在一起,不同列族的数据分开存储在不同的目录下。
一个表有多个列族,如果只是根据rowkey 而不指定列族进行检索,不同列族的数据需要独立进行检索,
性能必然会比指定列族的查询差很多,很多情况下甚至会有2~3倍的性能损失
优化建议:
尽量指定列族或者列进行精确查找。
4.离线批量读取请求是否设置禁止缓存?
优化原理:
通常在离线批量读取数据时会进行一次性全表扫描,一方面数据量很大,另一方面请求只会执行一次。
这种场景下如果使用 scan默认设置,就会将数据从HDFS加载出来放到缓存。
可想而知,大量数据进入缓存必将其他实时业务热点数据挤出,其他业务不得不从HDFS 加载,进而造成明显的读延迟毛刺。
优化建议:
离线批量读取请求设置禁用缓存, scanstCacheBlocks (false)。
13.5.3 HBase 列族设计优化
1.布隆过滤器是否设置?
优化原理:
布隆过滤器主要用来过滤不存在待检索rowkey的HFile文件,避免无用的IO操作
布隆过滤器取值有两个:row以及rowkey,需要根据业务来确定具体使用哪种。
如果业务中大多数随机查询仅仅使用row作为查询条件,布隆过滤器一定要设置为row;
如果大多数随机查询使用row+column作为查询条件,布隆过滤器需要设置为 rowcol。如果不确定业务查询类型,则设置为 row。
优化建议:
任何业务都应该设置布隆过滤器,通常设置为row,除非确认业务随机查类型为row+column,则设置为rowcol。
13.6 HBase 写人性能调优
HBase系统主要应用于写多读少的业务场景,通常来说对系统的写入吞吐量要求都比较高。 写入性能从 HBase服务器端和业务客户端两个角度分析
13.6.1 HBase 服务器端优化
1. Region 是否太少?
优化原理:
当前集群中表的Region个数如果小于Regionserver个数,即 Num(Region of Table)<Num (Regionserver),
可以考虑切分Region并尽可能分布到不同的Regionseve上以提高系统请求并发度
优化建议:
在Num(Region of Table)<Num (Regionserver)的场景下切分部分请负载高的Region,并迁移到其他Regionserver。
2.写入请求是否均衡?
优化原理:
写人请求如果不均衡,会导致系统并发度较低,还有可能造成部分节点负载很高,进而影响其他业务。
分布式系统中特别需要往意单个节点负载很高的情况,单个节点负载很高可能会拖慢整个集群,
这是因为很多业务会使用Mutl批量提交读写请求,一旦其中一部分请求落到慢节点无法得到及时响应,会导致整个批量请求超时。
优化建议:
检查 Rowkey设计以及预分区策略,保证写人请求均衡。
3.Utilze Flash storage for WAL
该特性会将WAL文件写到SSD上,对于写性能会有非常大的提升。
需要注意的是该特性建立在HDFs 2.6.0+以及HBase 1.1.0+版本基础上,以前的版本并不支持该符性。
使用该特性需要两个配置步骤:
1)使用HDFS Archival Storage机制,在确保物理机有SSD硬盘的前提下 配置HDFS的部分文件目录为ssD介质。
2)在hbase-sitexml中添加如下配置:
<property>
<name>hbase.wal.storage.policys></name>
<value>ONE_SSD</value>
<property>
hbase.wal.storage.policy默认为none,用户可以指定 ONE_SSD 或者ALL_SSD
ONE_SSD:WAL在HDFS上的一个副本文件写人SSD介质,另两个副本写人默认存储介质。
ALL_SSD:WAL的三个副本文件全部写人SSD介质。
13.6.2 HBase 客户端优化
1.是否可以使用Bulkload 方案写入?
Bukload是一个MapReduce程序,运行在Hadoop集群。程序的输人是指定数据源,输出是HFile 文件。
HFile文件生成之后再通过LoadlncremenalHFiles工具将HFile中相关元数据加载到HBase中。
Bukload方案适合将已经存在于HDFS上的数据批量导入HBase集群。
相比调用API的写人方案,Bulkload方案可以更加高效、快速地导入数据,而且对HBase集群几乎不产生任何影响。
2.是否需要写WAL? WAL 是否需要同步写入?
优化原理:
数据写入流程可以理解为一次顺序写WAL+一次写缓存,通常情况下写缓延迟很低 因此提升写入性能只能从WAL入手
HBase中可以通过设置 WAL的持久化等级 决定是否开启 WAL机制以及HLog的落盘方式。
WAL的持久化分为四个等级:SKP_WAL,ASYNC_WAL,SYNC_WAL以及FSYNC_WAL。
如果用户没有指定持久化等级,HBase默认使用SYNC WAL等级持久化数据。
在实际生产线环境中,部分业务可能并不特别关心异常情况下少量数据的丢失,而更关心数据写人香吐量。
比如某些推荐业务,这类业务即使丢失一部分用户行为数据可能对推荐结果也不会构成很大影响,
但是对于写人吞吐量要求很高,不能造成队列阻基。
这种场景下 下可以考虑关闭WAL写人。退而求其次,有些业务必须写WAL,但可以接受WAL异步写入,这是可以考虑优化的,通常也会带来一定的性能提升。
优化推荐:
根据业务关注点在WAL机制与写入吞吐量之间做出选择,用户可以通过客户端设置WAL持久化等级。
3. Put是否可以同步批量提交?
优化原理:
HBase分别提供了单条 put以及批量put的API接口,
使用批量 put接口 以减少客户端到RegionServer之间的RPC连接数,提高写入吞吐量。
另外需要注意的是, 批量 put 请求要么全部成功返回,要么抛出异常。
优化建议:
使用批量 put写人请求。
4.Put是否可以异步批量提交?
优化原理:
如果业务可以接受异常情况下少量数据丢失,可以使用异步批量提交的方式提父请求。
提交分两阶段执行:
用户提交写请求,数据写入客户端缓存,并返回用户写人成功;
当客户端缓存达到阅值(默认2M)后批量提交给Regionserver。
需要注意的是,在果些客户端异常的情况下,缓存数据有可能丢失。
优化建议:
在业务可以接受的情况下开启异步批量提交,用户可以设置 setAutoFlsh(false)
5.写入KeyValue 数据是否太大?
KeyValue大小对写人性能的影响巨大。一旦遇到写人性能比较差的情况,
需要分析写人性能下降是否因为写入KeyValue的数据太大。在这里插入代码片