HBase内容分享(八):货拉拉HBase Bulkload实践

本文详细描述了货拉拉在HBase数据导入过程中遇到的问题,如开发效率低、链路不稳定等,通过构建通用工具和优化Compaction、DistCp等技术,提升了数据导入的稳定性和效率,并分享了数据校验和稳定性保障措施。
摘要由CSDN通过智能技术生成

目录

引言

问题与挑战

调研

实践过程

Transform

Compaction工具

DistCp

数据校验

稳定性保障

总结


引言

HBase是基于Hadoop构建的一个高可用、高性能、支持水平扩展的NoSQL数据库,因其优秀的表现能力,多用在实时或准实时场景。在货拉拉,HBase承担了在线存储的职责,支持着风控、地图、实时标签等重要业务场景。

同时,在实际生产环境中,存在大量数据T+1的场景:即用户需要每日基于Hive中各系统的各类数据生成特定业务数据(如标签、指标等),定期将这部分数据(全量或增量)导入HBase系统,以提供在线服务查询,支撑风控、运营等场景。

问题与挑战

在初期,由于缺乏统一的离线数据导入流程,业务基于HBase Bulkload实现各自的Hive to HBase代码,在线上实践中,存在一些痛点与稳定性的风险,总结如下:

  1. 1. 开发效率低下重复开发,部分业务开发不熟悉大数据组件技术,耗时又耗力。

  2. 2. 缺少链路保障:部分业务对数据产出时间有较大依赖,对任务失败或延期、数据丢失等问题缺少发现能力。

  3. 3. 影响HBase稳定性:高峰期执行Bulkload造成多次线上隐患,甚至出现过用户将A集群HFile Load到B集群(由于B集群到A集群的NN端口不通),导致线上HBase 20min不可用。

因此,需要构建一套Hive To HBase的通用工具,并且保障整个数据链路的稳定性,主要需求点:

  1. 1. 简单通用:能满足绝大多数业务的数据转化需求,集成到数据开发平台,用户只需简单参数配置即可。

  2. 2. 可观测,可告警:能明确输入输出数据量,任务执行时间管理等。在任务异常(延时、报错等)时能主动通知到任务负责人,重要业务场景需执行对应的应急预案。

  3. 3. 可管控:依托数据开发平台,对任务变更、上线全流程增加审批管控,减少变更带来的稳定性风险。

调研

Hive To HBase的实现通常有两种架构,流程分别如下。

  • • 方案一

    图片

  1. 1. 在离线集群(YARN/HDFS/Hive混部集群)利用Spark/MR读取Hive数据转换成HBase内部数据格式,并直接将HFile写到在线HBase集群上。

  2. 2. 通过HBase内置工具LoadIncrementalHFile将生成的HFile加载到HBase集群中。

优缺点:

图片

  • • 方案二

图片

  1. 1. Transform阶段将HFile写到离线集群中。

  2. 2. 引入Hadoop DistCp工具,依赖其灵活的限速配置,将生成好的HFile拷贝到在线HBase集群中。

结论:由于不限速对在线HBase存在较大稳定性隐患,最终使用了方案二来实现。

实践过程

Transform

关于数据处理的实现逻辑,社区中有较多优秀的实践,这里就不再展开。在货拉拉的实际生产中,大部分业务的需求场景比较简单,使用统一的Transform流程即可,但也存在由于业务特性,需要定制化实现的场景,本次仅介绍统一方案。为了便于使用,程序封装在脚本中,集成在数据开发平台作为模版任务,用户仅需配置几个简单参数即可创建任务,实现数据处理,方便快捷。

脚本具备如下特性:

  • • 多RowKey生成策略:自定义RowKey设计,例如Hash,加盐和截取字段。

  • • 列名映射:支持HBase表列名与Hive列名的自定义映射,不需要强求按照hive表的字段名字或顺序。

任务上线后,在生产环境灰度时,也发现了如下问题:

  1. 1. 触发Compact高峰,抢占资源:风控业务每次为单个Region生成多个HFile(单个文件比较小),在CompactionChecker的下次检测时,会触发Compact高峰大量占用CPU和IO资源,并且这个数据导入任务依赖公司离线报表,离线报表产出发生延时后,Bulkload操作就可能在业务高峰期才被执行,对HBase在线服务存在较大的稳定性风险。

  2. 2. 数据本地率低,查询P99上涨:Distcp随机选择DN节点进行拷贝,这会导致HBase表的本地率下降,对于延时较为敏感的业务场景,是不可接受的。

针对上述两个问题,结合业务特点的分析,提出整体的解决方案

  1. 1. 业务合并任务,减少为一个Region生成的HFile数量。

  2. 2. 优化表级Compaction配置,尽量在Bulkload后不触发Compaction(可以在Transform过程中设置hbase.mapreduce.hfileoutputformat.compaction.exclude 来避免)。

  3. 3. 部分业务不能设置TTL,此时Bulkload的文件无法被Minor Compaction清理,为避免单个Region下文件数不断增加,通过一个外挂的Major Compaction工具,在业务低峰期调起Major Compaction来合并HFile。

  4. 4. 改造Distcp,支持设置favoredNodes,提高数据本地率。

Compaction工具

在进行了HFile数优化和Compact配置的调整后,业务在Bulkload的查询抖动得到了明显的改善:

图片

优化前

图片

优化后

但由于业务特性,这部分业务表不能设置TTL,所以只能通过Major Compact来清理数据与降低HFile数。为了避免在高峰期执行Major Compact,关闭了默认的Major Compact,并且实现了一套Major Compact工具,支持多种调度策略:

  1. 1. OffpeakCompact:用来控制低峰期才提交Compact任务,具体的Region选举策略为如下几个。

  2. 2. TimeCompact:基于时间间隔的策略,计算Region上一次Major Compact与当前时间之差。

  3. 3. FileNumberCompact:计算Region的Store中的HFile数是否超过配置值。

效果
上线运行了一段时间,观察合理控制了表的HFile数量,同时规避了Bulkload后的Compact高峰。

但也在实际的运行中,发现一些问题:

  1. 1. 存在一些Region的lastMajorCompactionAge始终为0,这就导致使用TimeCompact策略时是失效的。通过分析,发现Bukload的HFile文件中的create_time_ts为0 。

    图片

    再结合代码分析,发现HFileOutputFormat2在构建HFile时未设置CreateTime,代码如下:

 //1.生成HFile时创建writer
HFileOutputFormat2.getNewWriter()

    HFileContextBuilder contextBuilder = new HFileContextBuilder()
            .withCompression(compression)
            .withChecksumType(HStore.getChecksumType(conf))
            .withBytesPerCheckSum(HStore.getBytesPerChecksum(conf))
            .withBlockSize(blockSize);
            
//2.load HFile时split HFile
LoadIncrementalHFiles.copyHFileHalf()
    HFileContext hFileContext = new HFileContextBuilder().withCompression(compression)
        .withChecksumType(HStore.getChecksumType(conf))
        .withBytesPerCheckSum(HStore.getBytesPerChecksum(conf)).withBlockSize(blocksize)
        .withDataBlockEncoding(familyDescriptor.getDataBlockEncoding()).withIncludesTags(true)
        .build();
    halfWriter = new StoreFileWriter.Builder(conf, cacheConf, fs).withFilePath(outFile)
        .withBloomType(bloomFilterType).withFileContext(hFileContext).build();

优化了相关代码后,整体运行结果符合预期,同时也将这部分回馈到了社区,相关JIRA:HBASE-27636HBASE-27688PHOENIX-6955

  1. 2. 尽管配置了Off-peak Compactions,但在业务低峰期依旧不能充分利用集群资源去合并HFile。通过分析,发现目前的Off-peak Compactions是全局比较,同一时间只能运行一个Off-peak的Compact。关键代码如下:

private static final AtomicBoolean offPeakCompactionTracker = new AtomicBoolean(); 

// Normal case - coprocessor is not overriding file selection.
if (!compaction.hasSelection()) {
 boolean isUserCompaction = priority == Store.PRIORITY_USER;
 boolean mayUseOffPeak =
   offPeakHours.isOffPeakHour() && offPeakCompactionTracker.compareAndSet(false, true);
 try {
   compaction.select(this.filesCompacting, isUserCompaction, mayUseOffPeak,
     forceMajor && filesCompacting.isEmpty());
 } catch (IOException e) {
   if (mayUseOffPeak) {
     offPeakCompactionTracker.set(false);
   }
   throw e;
 }
 assert compaction.hasSelection();
 if (mayUseOffPeak && !compaction.getRequest().isOffPeak()) {
   // Compaction policy doesn't want to take advantage of off-peak.
   offPeakCompactionTracker.set(false);
 }

针对此处的优化,我们正在内部进行相关的优化验证,也创建了相关JIRA:HBASE-27861,希望能与社区一起讨论。

DistCp

对于延时要求较高的业务,数据本地率对其RT的P99P999影响较大,尽管HBase在 HBASE-12596 中优化了Bulkload的数据本地率,但使用DistCp后,数据本地率则无法保障。对此针对DistCp工具进行改造并且封装成新的工具,具备如下特性:

  1. 1. 指定FavoredNodes:支持为不同的HFile文件设置特定的FavoredNodes。

  2. 2. 多集群拷贝:用户只需简单配置目标集群名,并可完成同份数据拷贝到集群。

对于DistCp的改造,部分能力已开源,参见 HADOOP-18629。同时也针对HBase进行两项对应的优化,见:HBASE-27670HBASE-27733

数据校验

部分业务非常在意Bulkload后数据的质量,有多少数据成功落HBase,是否存在丢数等。为解决用户的担忧,保证数据的正确性和可靠性,主要进行了如下验证:

  1. 1. Bulkload流程验证,通过如下指标判断完成度

    • • Transform:实现Counter计算行数。

    • • Distcp:拷贝前后HFile目录总大小。

    • • Load:HFile文件是否被清空,表级Bulkload的相关监控。

  2. 2. 抽样验数,用户指定RowKey查询HBase表。

稳定性保障

数据链路作为服务的延伸,在整体的稳定性保障中也相当重要,对此我们也构建了对应的链路稳定性保障方案(方案如下),从而提升整体的稳定性,目前能力基本已落地或正在落地。

图片

总结

本文从用户痛点与服务稳定性的角度出发,介绍了货拉拉大数据基础架构团队在HBase离线数据链路保障上的思考与实践。希望能为读者提供一些参考,也欢迎与我们沟通交流。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值