问题简述
Bulk load主要面向需要大批量的向HBase导入数据的场景。这种方式是先生成HBase的底层存储文件 HFile,然后直接将这些 HFile 移动到HBase的存储目录下。它相比调用HBase的put API添加数据,处理效率更快并且对HBase 运行影响更小。
业务使用bulkload+scan的模式非常普遍,往往是一个离线任务bulkload一批文件后,就启动另一个离线任务去读所有bulkload过的数据。普遍存在的问题是,bulk load后scan全表时请求处理慢。
且这种情况同时可能伴随高CPU load,导致整个RS的全部region请求都受影响。
优化方向
bulk load的最后阶段,通过RPC向region导入文件时,由于只是进行非常轻量级的文件移动,所以对于region内部来说,短时间内新增了大量导入的文件。
进行查询时,对于单region来说,需要对其内部所有的文件来进行解压和堆排序。
所以,文件的数量大小,是这里影响性能的关键因素。根据线上现象观察,单Region 上千级别文件的查询,可以引起全表扫描时,cpu busy的百分比显著上升。
HBase减少文件数量的方式只有compaction。所以,提升bulk load过程中的compaction效率,可以缓解scan时的性能问题。
但是注意单次compact的文件数量不能过多,比如我们曾经遇到使用StripeStoreEngine时,单次compact全部L0的文件,而bulkload又是所有文件先进L0,就造成了单个compact任务选中上万文件而长时间无法结束的问题。
社区方案
HBase社区提出了bulk load后主动触发compaction的优化方案,HBASE-25213 Should request Compaction after bulkLoadHFiles is done。
但是社区的方案是在每个文件bulk load后,都进行了compaction文件的force select,所以会导致compaction引起的CPU load过高问题。
而且社区之后添加了HBASE-25213功能的开关(HBASE-25630 Set switch compaction after bulkload default as false),来规避CPU load高的问题。
针对社区方案的优化
bulk load后主动检查region是否需要compact,将comapct请求放入队列,等待调度线程根据每次放入队列时检查优先级来判断是否需要立即选择文件进行compact。提到社区的issue:HBASE-26249 Ameliorate compaction made by bulk-loading files