来自字节跳动的管梓越同学一篇关于Apache Hudi在字节跳动推荐系统中EB级数据量实践的分享。

接下来将分为场景需求、设计选型、功能支持、性能调优、未来展望五部分介绍Hudi在字节跳动推荐系统中的实践。

在推荐系统中,我们在两个场景下使用数据湖

  1. 我们使用BigTable作为整个系统近线处理的数据存储,这是一个公司自研的组件TBase,提供了BigTable的语义和搜索推荐广告场景下一些需求的抽象,并屏蔽底层存储的差异。为了更好的理解,这里可以把它直接看做一个HBase。在这过程中为了能够服务离线对数据的分析挖掘需求,需要将数据导出到离线存储中。在过去用户或是使用MR/Spark直接访问存储,或是通过扫库的方式获取数据,不符合OLAP场景下的数据访问特性。因此我们基于数据湖构建BigTable的CDC,提高数据时效,减少近线系统访问压力,提供高效的OLAP访问和用户友好的SQL消费方式。
  2. 除此之外,我们还在特征工程与模型训练的场景中使用数据湖。我们从内部和外部分别获得两类实时数据流,一个是来自系统内部回流的Instance,包含了推荐系统Serving时获得的Feature。另一种是来自端上埋点/多种复杂外部数据源的反馈,这类数据作为Label,和之前的feature共同组成了完整的机器学习样本。针对这个场景,我们需要实现一个基于主键的拼接操作,将Instance和Label Merge到一起。开窗范围可能长达数十天,千亿行量级。需要支持高效得列式选取和谓词下推。同时还需要支持并发Update等相关能力。

在这两个场景下存在如下挑战

  1. 数据的非常不规整。相比Binlog,WAL没法获得一行的全部信息,同时数据大小变化非常大。
  2. 吞吐量比较大,单表吞吐超百GB/s,单表PB级存储。
  3. 数据Schema 复杂。数据存在高维、稀疏等现象。表列数从1000-10000+都有。并且有大量复杂数据类型。

在引擎选型时,我们考察过Hudi,Iceberg,DeltaLake三个最热门的数据湖引擎。三者在我们的场景下各有优劣,最终基于Hudi对上下游生态的开放,对全局索引的支持,对若干存储逻辑提供了定制化的开发接口等原因,选择了Hudi作为存储引擎。

  • 针对实时写入,选择了时效性更好的MOR。
  • 考察了索引类型,首先因为WAL不能每次都获取到数据的分区,所以必须要全局索引。在几种全局索引实现中,为了实现高性能的写入,HBase是唯一的选择。另外两种的实现决定了都和HBase在性能有本质上的差距。
  • 在计算引擎上和API上,当时Hudi对Flink的支持还不是特别完善,所以选择了更为成熟的Spark,为了能灵活实现一些定制功能和逻辑,也因为DataFrame的API语义限制比较多,所以选择了更底层的RDD API。

功能支持包括存储语义的MVCC和Schema注册系统。

首先为了支持WAL语义的写入,我们实现了针对MVCC的Payload,基于Avro自定义了一套带时间戳的数据结构实现。并通过视图访问的方式对用户屏蔽了这套逻辑。除此之外还实现了HBase Append的语义,可以实现对List类型的追加写而非覆盖写。

由于Hudi本身的Schema从Write的数据中获取,这种方式和其他系统对接不是很方便,以及我们需要一些基于Schema的扩展功能,所以我们构建了一个元数据中心来提供元数据相关的操作。

  • 首先我们基于一种内部的存储提供的语义实现了原子变更和异地多活。用户可以通过接口原子地触发Schema变更并立刻获得结果。

  • 并通过加入版本号的方法实现了Schema的多版本,Schema而不是把Json传来传去。有了多版本也可以实现Schema更灵活的演进。

  • 我们还支持了列级别的额外信息编码,来帮助业务实现一些场景下特有的扩展功能。并把列名替换成了数字来节约使用过程中的开销。

  • Hudi的Spark Job在使用的时候会在JVM级别构建一个local cache并通过pull的方式和元数据中心同步数据,实现Schema的快速访问和进程内Schema的单例。

在我们场景下性能挑战比较大,最大单表数据量达400PB+,日增PB级数据量,总数据量达EB级别,因此我们针对性能和数据特性开发做了一些工作来提高性能。

序列化方面包括如下优化

  1. Schema:数据使用Avro序列化开销特别大,而且消耗资源也非常多。针对这个问题,我们首先借助Schema的JVM单例,规避了序列化过程中很多费CPU的比较操作。
  2. 通过优化Payload逻辑,减少了需要序列化的次数。
  3. 借助了第三方的Avro序列化实现,通过将序列化过程编译成字节码的方式来提高SerDe的速度以及降低内存占用。对这种序列化形式做了修改,以保证我们的复杂Schema也能够正常编译。

对于Compaction流程优化如下

  • Hudi除了默认的Inline/Async compaction选项之外,还支持Compaction的灵活部署。Compaction Job的作业特性和Ingestion作业其实有较大区别。在同一个Spark Application当中不仅不能针对性设置,也存在资源弹性不足的问题。我们首先构建了独立部署的脚本,让Compaction作业可以独立触发运行。使用了低成本的混部队列并可以针对此次Compaction的Plan做资源申请。除此之外还做了基于规则和启发式的Compaction Strategy,用户的需求通常是保证天级别或者小时级别的SLA,并针对性地压缩某些分区的数据,所以提供了针对性压缩的能力。
  • 为了能缩短关键Compaction的时间,我们通常会提前做Compaction来避免所有工作都在一个Compaction Job中完成。但是如果一个Compact过的FileGroup又有新的Update,就不得不再次Compact。为了优化整体的效率,我们根据业务信息对一个FileGroup该在何时被压缩做了启发式的调度以减少额外的压缩损耗。该特性的具体收益还在评估中。
  • 最后我们对Compaction做了一些流程的优化,比如不使用WriteStatus的Cache等等。

HDFS作为一种面向吞吐设计的存储,在集群水位比较高的情况下,实时写入毛刺比较严重。通过和HDFS团队的沟通与合作,做了相关的一些工作。

  • 首先把原有的数据HSync操作替换为HFlush,避免了分散性update导致的磁盘IO写放大。
  • 针对场景调参做了激进的pipeline切换设置,并且HDFS团队开发了灵活的可以控制pipeline的api,来实现这个场景下灵活的配置。
  • 最后还通过logfile独立IO隔离的方式保证了实时写入的时效性。

还有一些零零碎碎的性能提升,流程修改和Bug Fix,大家感兴趣可以找我交流。

未来我们会在以下几个方面持续迭代。

  • 产品化问题:目前使用的API和调参调优方式对用户要求很高,尤其是调参和运维,需要对Hudi原理有相当的了解才可以完成,不利于用户推广使用。

  • 生态对接问题:在我们的场景中,技术栈以Flink为主,未来会探索Flink的使用。除此之外上下游使用的应用和环境也比较复杂,非常需要跨语言和通用的接口实现。目前和Spark绑定过于严重。

  • 成本和性能问题:老生常谈的话题,由于我们场景比较大,所以在这块优化上的收益非常可观。

  • 存储语义:我们把Hudi当做一种存储来使用而非一种表格式。所以未来会拓展Hudi的使用场景,需要更丰富的存储语义,会在这方面做更多的工作。

最后打个广告,目前我们推荐架构团队正在招人,工作地包括:北京/上海/杭州/新加坡/山景城等,有兴趣的小伙伴可以添加微信qinglingcannotfly或发送简历至邮箱: guanziyue.gzy@bytedance.com

字节跳动基于Apache Hudi构建EB级数据湖实践的更多相关文章

  1. Uber基于Apache Hudi构建PB级数据湖实践

    1. 引言 从确保准确预计到达时间到预测最佳交通路线,在Uber平台上提供安全.无缝的运输和交付体验需要可靠.高性能的大规模数据存储和分析.2016年,Uber开发了增量处理框架Apache Hudi ...

  2. 基于Apache Hudi构建分析型数据湖

    为了有机地发展业务,每个组织都在迅速采用分析. 在分析过程的帮助下,产品团队正在接收来自用户的反馈,并能够以更快的速度交付新功能. 通过分析提供的对用户的更深入了解,营销团队能够调整他们的活动以针对特 ...

  3. 基于Apache Hudi构建数据湖的典型应用场景介绍

    1. 传统数据湖存在的问题与挑战 传统数据湖解决方案中,常用Hive来构建T+1级别的数据仓库,通过HDFS存储实现海量数据的存储与水平扩容,通过Hive实现元数据的管理以及数据操作的SQL化.虽然能 ...

  4. 基于 Apache Hudi 构建增量和无限回放事件流的 OLAP 平台

    1. 摘要 在本博客中,我们将讨论在构建流数据平台时如何利用 Hudi 的两个最令人难以置信的能力. 增量消费--每 30 分钟处理一次数据,并在我们的组织内构建每小时级别的OLAP平台 事件流的无限 ...

  5. 基于Apache Hudi 的CDC数据入湖

    作者:李少锋 文章目录: 一.CDC背景介绍 二.CDC数据入湖 三.Hudi核心设计 四.Hudi未来规划 1. CDC背景介绍 首先我们介绍什么是CDC?CDC的全称是Change data Ca ...

  6. 触宝科技基于Apache Hudi的流批一体架构实践

    1. 前言 当前公司的大数据实时链路如下图,数据源是MySQL数据库,然后通过Binlog Query的方式消费或者直接客户端采集到Kafka,最终通过基于Spark/Flink实现的批流一体计算引擎 ...

  7. OnZoom 基于Apache Hudi的流批一体架构实践

    1. 背景 OnZoom是Zoom新产品,是基于Zoom Meeting的一个独一无二的在线活动平台和市场.作为Zoom统一通信平台的延伸,OnZoom是一个综合性解决方案,为付费的Zoom用户提供创 ...

  8. 基于 Apache Hudi 和DBT 构建开放的Lakehouse

    本博客的重点展示如何利用增量数据处理和执行字段级更新来构建一个开放式 Lakehouse. 我们很高兴地宣布,用户现在可以使用 Apache Hudi + dbt 来构建开放Lakehouse. 在深 ...

  9. 基于Apache Hudi + Flink的亿级数据入湖实践

    本次分享分为5个部分介绍Apache Hudi的应用与实践 实时数据落地需求演进 基于Spark+Hudi的实时数据落地应用实践 基于Flink自定义实时数据落地实践 基于Flink+Hudi的应用实 ...

随机推荐

  1. Spring总结之IOC

    一.Spring IOC 简介 IOC(Inverse of control):控制反转,又称作依赖注入,主要是把创建对象和查找依赖对象的控制权交给IOC容器,由IOC容器管理对象的生命周期,是一种重 ...

  2. 查看JVM默认参数及微调JVM启动参数

    目录 查看某个JVM进程堆内存信息 微调JVM启动参数 查看JVM的一些默认参数 参考廖雪峰老师的这篇 JVM调优的正确姿势: https://www.liaoxuefeng.com/article/ ...

  3. Java 使用新方法打印Word文档

    前言 我曾写过一篇文章,它主要介绍了如何通过物理打印机和虚拟打印机来打印Word文档.今天这篇教程将介绍一种新的方法来实现对Word文档的打印. 此次使用到的类库仍然是Spire.Doc for Ja ...

  4. 第十篇 -- 下拉列表框QComboBox

    效果图: ui_ComboBox.py # -*- coding: utf-8 -*- # Form implementation generated from reading ui file 'ui ...

  5. python虚拟环境之Pyenv

    一.windows下安装 1.使用命令安装 pip install pyenv-win --target %USERPROFILE%/.pyenv %USERPROFILE%/是具体的路径,例如 ## ...

  6. 记录一个SQL语句 case select 1

    select Code, CodeName, CodeAlias, ComCode, OtherSign from ldcode where codetype = 'edorapptype' and ...

  7. SQL Server常用的几个存储过程

    1. sp_helptext 查看一些数据库对象的定义,比如存储过程.函数.试图等. 2. sp_who或者sp_who2 查看SQL Server数据库会话信息.比如是否被阻塞.

  8. 声明提前(hoist)

    程序执行前,都会先找到var声明的变量和function声明的函数. 一.var声明的变量 程序 结果 console.log(a); var a=10; console.log(a); //unde ...

  9. Python - 解包的各种骚操作

    为什么要讲解包 因为我觉得解包是 Python 的一大特性,大大提升了编程的效率,而且适用性很广 啥是解包 个人通俗理解:解开包袱,拿出东西 正确理解:将元素从可迭代对象中一个个取出来 python ...

  10. 从理发店小弟到阿里P10大牛,一位高中学渣的“登天”之路

    蚂蚁金服,可能是众多程序猿眼中梦寐以求的归宿,无数拿过数不清奖状的各个高校走出的学子精英都挤破头皮,只为能在蚂蚁占有一席之地. 蚂蚁金服里不乏各种深藏不露的大佬,到了那里才会深刻明白一山还有一山高这句 ...