HBase 写入性能优化
前言
本文主要借阅于《HBase原理与实践》这本书,可以自行查阅 13.6 章
可以从HBase服务器端和业务客户端两个角度分析,确认是否还有提高的空间
客户端优化
是否可以使用 Bulkload 方案写入?
Bulkload 是一个 MapReduce 程序(当然,也可以自行改成 Spark 程序)运行在Hadoop集群。程序的输入是指定数据源,输出是 HFile 文件。HFile 文件生成之后再通过 LoadIncrementalHFiles 工具将 HFile 中相关元数据加载到 HBase 中。
Bulkload 方案适合将已经存在于 HDFS 上的数据批量导入 HBase 集群。相比调用API的写入方案,Bulkload 方案可以更加高效、快速地导入数据,而且对 HBase 集群几乎不产生任何影响。
关于 Bulkload 可以阅读《HBase原理与实践》6.2 章
是否需要写 WAL? WAL 是否需要同步写入?
优化原理: 数据写入流程可以理解为一次顺序写WAL+一次写缓存,通常情况下写缓存延迟很低,因此提升写性能只能从WAL入手。HBase中可以通过设置WAL的持久化等级决定是否开启WAL机制以及HLog的落盘方式。WAL的持久化分为四个等级:SKIP_WAL,ASYNC_WAL,SYNC_WAL以及FSYNC_WAL。如果用户没有指定持久化等级,HBase默认使用SYNC_WAL等级持久化数据。
在实际生产线环境中,部分业务可能并不特别关心异常情况下少量数据的丢失,而更关心数据写入吞吐量。比如某些推荐业务,这类业务即使丢失一部分用户行为数据可能对推荐结果也不会构成很大影响,但是对于写入吞吐量要求很高,不能造成队列阻塞。这种场景下可以考虑关闭WAL写入。退而求其次,有些业务必须写WAL,但可以接受WAL异步写入,这是可以考虑优化的,通常也会带来一定的性能提升。
优化推荐: 根据业务关注点在WAL机制与写入吞吐量之间做出选择,用户可以通过客户端设置WAL持久化等级。
Put 是否可以同步批量提交?
优化原理: HBase分别提供了单条put以及批量put的API接口,使用批量put接口可以减少客户端到RegionServer之间的RPC连接数,提高写入吞吐量。另外需要注意的是,批量put请求要么全部成功返回,要么抛出异常。
优化建议: 使用批量put写入请求。
Put 是否可以异步批量提交?
优化原理: 如果业务可以接受异常情况下少量数据丢失,可以使用异步批量提交的方式提交请求。提交分两阶段执行:用户提交写请求,数据写入客户端缓存,并返回用户写入成功;当客户端缓存达到阈值(默认2M)后批量提交给RegionServer。需要注意的是,在某些客户端异常的情况下,缓存数据有可能丢失。
优化建议: 在业务可以接受的情况下开启异步批量提交,用户可以设置setAutoFlush (false)
写入 KeyValue 数据是否太大?
KeyValue大小对写入性能的影响巨大。一旦遇到写入性能比较差的情况,需要分析写入性能下降是否因为写入KeyValue的数据太大。
KeyValue大小对写入性能影响曲线如下
横坐标是写入的一行数据(每行数据10列)大小,左纵坐标是写入吞吐量,右纵坐标是写入平均延迟(ms)。可以看出,随着单行数据不断变大,写入吞吐量急剧下降,写入延迟在100K之后急剧增大。
服务端优化
Region 是否太少?
优化原理: 当前集群中表的Region个数如果小于RegionServer个数,即Num (Region of Table)< Num (RegionServer),可以考虑切分Region并尽可能分布到不同的RegionServer上以提高系统请求并发度。
写入请求是否均衡?
优化原理: 写入请求如果不均衡,会导致系统并发度较低,还有可能造成部分节点负载很高,进而影响其他业务。分布式系统中特别需要注意单个节点负载很高的情况,单个节点负载很高可能会拖慢整个集群,这是因为很多业务会使用Mutli批量提交读写请求,一旦其中一部分请求落到慢节点无法得到及时响应,会导致整个批量请求超时。
优化建议: 检查Rowkey设计以及预分区策略,保证写入请求均衡。
Utilize Flash storage for WAL
该特性会将WAL文件写到SSD上,对于写性能会有非常大的提升。需要注意的是,该特性建立在HDFS 2.6.0+以及HBase 1.1.0+版本基础上,以前的版本并不支持该特性。
使用该特性需要两个配置步骤:
1) 使用HDFS Archival Storage机制,在确保物理机有SSD硬盘的前提下配置HDFS的部分文件目录为SSD介质
2) 在hbase-site.xml中添加如下配置
1
2
3
4
5
6<configuration>
<property>
<name>hbase.wal.storage.policy</name>
<value>ONE_SSD</value>
</property>
</configuration>
hbase.wal.storage.policy默认为none,用户可以指定ONE_SSD或者ALL_SSD
- ONE_SSD: WAL在HDFS上的一个副本文件写入SSD介质,另两个副本写入默认存储介质
- ALL_SSD: WAL的三个副本文件全部写入SSD介质
写入问题
- 写阻塞
- MemStore 占用内存超过 RegionServer 级别高水位阈值导致阻塞 (hbase.regionserver.global.memstore.size)
- RegionServer Active Handler 资源被耗尽 (可能跟KeyValue太大有关)
- Store 中 HFile 文件数量达到阈值就会阻塞写入 (hbase.hstore.blockingStoreFiles)
- 写延迟
- WAL 写入延迟,IO 资源是否争抢 (Utilize Flash storage for WAL)
- JVM young gc (CCSMap)
参考链接