T3出行的杨华和张永旭描述了他们数据湖架构的发展。该架构使用了众多开源技术,包括Apache Hudi和Alluxio。在本文中,您将看到我们如何使用Hudi和Alluxio将数据摄取时间缩短一半。此外,数据分析人员如何使用Presto、Hudi和Alluxio让查询速度提高了10倍。我们基于数据编排为数据管道的多个阶段(包括提取和分析)构建了数据湖。
1.T3出行数据湖总览
T3出行当前还处于业务扩张期,在构建数据湖之前不同的业务线,会选择不同的存储系统、传输工具以及处理框架,从而出现了严重的数据孤岛使得挖掘数据价值的复杂度变得非常高。由于业务的迅速发展,这种低效率成为了我们的工程瓶颈。
我们转向了基于阿里巴巴OSS(类似于AWS S3的对象存储)的统一数据湖解决方案,以遵循多集群、共享数据架构(Multi-cluster,Shared-data Architecture)的设计原则提供集中位置来存储结构化和非结构化数据。与不同的数据孤岛相反,所有应用程序都将OSS存储作为事实的来源来访问。这种体系结构使我们能够按原样存储数据, 而不必先对数据进行结构化,并运行不同类型的分析以指导更好的决策,通过大数据处理,实时分析和机器学习来构建仪表板和可视化。
2.使用Hudi进行高效的近实时分析
T3出行的智能出行业务推动了对近实时处理和分析数据的需求。使用传统的数据仓库,我们面临以下挑战:
- 长尾更新引发冷数据频繁与级联更新
- 超长的业务窗口导致订单分析回溯成本高
- 随机更新及迟到数据无法预判
- 数据摄取Pipeline无法保证可靠性
- 分布式数据Pipeline中丢数据无法对账
- 数仓数据摄取的延迟性很高
因此,我们在OSS之上采用了Apache Hudi来解决这些问题。下图展示了Hudi的体系结构:
2.1启用近实时数据摄取和分析
T3出行数据湖支持Kafka 消息、Mysql binlog、GIS、业务日志等多种数据源近实时入湖,全公司60%以上的数据已经存入数据湖,并且这个比例还在不断扩大。T3出行通过在数据管道中引入Hudi将数据的摄取时间缩短至几分钟,再结合大数据交互式查询与分析框架(如Presto和SparkSQL),可以实现更实时地对数据进行洞察、分析。
2.2启用增量处理管道
T3出行借助于Hudi提供的增量查询的能力,对于频繁变更场景中的多层数据加工的场景,可以只将增量的变更反馈给下游的派生表,下游的派生表只需要应用这些变更数据,就可以快速完成多层链路的局部数据更新,从而极大地降低了频繁变更场景下的数据更新的效率。有效地避免了传统Hive数仓中的全分区、冷数据更新。
2.3使用Hudi作为统一数据格式
传统的数据仓库通常部署Hadoop来存储数据并提供批处理分析,Kafka单独用于将数据分发到其他数据处理框架,从而导致数据重复。Hudi有效解决了这个问题,我们始终使用Spark-kafka管道将最新更新的数据插入到Hudi表中,然后以增量方式读取Hudi表的更新。换句话说,Hudi统一了存储。
3.使用Alluxio进行高效的数据缓存
在早期版本的数据湖中并没有使用Alluxio,Spark实时处理从Kafka接收的数据,然后使用Hudi DeltaStreamer任务将其写入OSS。执行这个流程时,Spark在直接写入OSS时网络延迟通常非常高。因为所有数据都存储在OSS中,导致数据缺失本地性,所以对Hudi数据的OLAP查询也非常慢。为了解决延迟问题,我们将Alluxio部署为数据编排层,与Spark和Presto等计算引擎共置一处,并使用Alluxio加速了对数据湖的读写,如下图所示:
Hudi,Parquet,ORC和JSON等格式的数据大部分存储在OSS上,占95%的数据。Flink,Spark,Kylin和Presto等计算引擎分别部署在隔离的群集中。当每个引擎访问OSS时,Alluxio充当虚拟分布式存储系统来加速数据,并与每个计算群集共存。下面介绍一下T3出行数据湖中使用Alluxio的案例。
3.1数据入湖
我们将Alluxio与计算集群共置部署。在数据入湖前,将对应的OSS路径挂载至alluxio文件系统中,然后设置Hudi的"--target-base-path"参数 从oss://... 改为 alluxio://... 。在数据入湖时,我们使用Spark引擎拉起Hudi程序不断摄入数据,数据此时在alluxio中流转。Hudi程序拉起后,设置每分钟将数据从Allxuio缓存中异步同步至远程OSS。这样Spark从之前的写远程OSS转变为写本地的Alluxio,缩短了数据入湖的时长。
3.2湖上数据分析
我们使用Presto作为自助查询引擎,分析湖上的Hudi表。在每一个Presto worker节点共置Alluxio。当Presto与Alluxio服务共置运行时,Alluxio可能会将输入数据缓存到Presto worker的本地,并以内存速度提供下次检索。在这种情况下,Presto可以利用Alluxio从本地的Alluxio worker存储读取数据(称之为短路读取),无需任何额外的网络传输。
3.3跨多个存储系统的并发访问
为了确保训练样本的准确性,我们的机器学习团队经常将生产中的脱敏数据同步到离线机器学习环境。在同步期间,数据跨多个文件系统流动,从生产OSS到线下数据湖集群HDFS,最后同步到机器学习集群的HDFS。对于数据建模人员来说,数据迁移过程不仅效率低下,而且会因错误配置而导致出错,因为其中涉及多个不同配置的文件系统。于是我们引入Alluxio,将多个文件系统都挂载到同一个Alluxio下,统一了命名空间。端到端对接时,使用各自的Alluxio路径,这保证了具有不同API的应用程序无缝访问和传输数据。这种数据访问布局还可以提高性能。
3.4基准测试
总体而言,我们观察到了Alluxio的以下优势:
- Alluxio 支持层次化且透明的缓存机制;
- Alluxio 支持读取时缓存 promote 模式;
- Alluxio 支持异步写模式;
- Alluxio 支持 LRU 回收策略;
- Alluxio 拥有 pin 以及 TTL 特性;
经过比较和验证后,我们选择使用Spark SQL作为查询引擎,查询了Hudi表,存储层分别是Alluxio + OSS、OSS、HDFS这三组不同文件系统。压测时发现,数据量大于一定量级(2400W)后,使用alluxio+oss的查询速度超越了混合部署的HDFS查询速度,数据量大于1E后,查询速度开始成倍提升。到达6E数据后,相对于查询原生oss达到12倍提升,相对于查询原生HDFS达到8倍提升。数据规模越大,性能提升越显著,提升的倍数取决于机器配置。
4.展望
随着T3出行的数据湖生态系统的扩展,我们将继续面对计算和存储隔离的关键场景随着T对数据处理需求的增长,我们的团队计划大规模部署Alluxio,以加强数据湖查询能力。所以除了数据湖计算引擎(主要是Spark SQL)上会部署Alluxio外,后续在OLAP集群(Apache Kylin)和ad_hoc集群(Presto)上架一层Alluxio。Alluxio将覆盖全场景,每个场景间Alluxio互联,提升数据湖以及围湖生态的读写效率。
5.结论
正如前面所讲,Alluxio覆盖了Hudi近实时摄取,近实时分析,增量处理,DFS上数据分发等所有场景,在数据入湖和湖上数据分析链路上都扮演了强力加速器的角色,两者可谓强强联手。落地到具体场景上,研发工程师将数据入湖时间缩短了1-2倍。数据分析人员使用Presto+Hudi+Alluxio查询湖上数据的速度提高了10倍以上。Alluxio是T3出行成为中国领先的企业级数据湖计划中重要组成部分,我们期待在T3出行的数据湖生态系统中与Alluxio进一步集成。