QCon-OPPO数据平台CloudLake降本增效实践

1. 背景

OPPO从19年开始,用了两年时间,以K8S,容器化为核心,完成了公司混合云建设,并实现100%在线业务上云。OPPO的业务,目前覆盖国内,南亚,欧洲,美洲,在国内我们有自己的机房,在海外,更多是和公有云合作 ,有AWS,Google。 OPPO的云是朵云上云,与共有云的合作,更多只是采购机器资源,部署我们自己的服务。OPPO云给我司带来了数亿的降本红利,得到了公司的广泛认可。

图1 OPPO混合云

目前OPPO的数据平台规模,计算资源近万台,存储接近1个EB,离线任务数近百万,实时任务数千。统计我们过去几年的增速,平均下来,每年大概有30%的规模增长。如此的一个规模增长下,系统SLA三个9,任务100%准点,是我们必须要保障的,同时,公司希望数据平台能够把过往快速增长的成本降下来。所以 业务快速增长、系统SLA和任务准点率保持高水平的前提下,如何进一步降本增效是我们必须要解决的问题。

图2 OPPO数据平台业务规模

对于这样一个问题,我们的解法是进行一系列的技术升级,主要包括批流一体、云数融合调度、数据湖存储三个方面。

2. 批流一体

图3 批流一体架构

如上图,上半部分,典型的Lambda架构。批流两条计算链路,元数据分开。应用侧的多种OLAP引擎,也有各自的存储方法与元数据管理。

我们通常说的批流一体,一般涉及到三个方面的统一,元数据,存储,引擎。这三方面,OPPO更看重前两点。为了元数据的统一,我们以HMS服务为主,同时通过Waggle-Dance进行了加固。为了存储的统一,我们引入了Iceberg ,打破实时数仓,离线数据的存储边界,同时提高数据仓库的实时性。

图4 Iceberg

最近两年,开源界以Delta, Hudi, Iceberg为代表的Data Lake  Format非常流行。他们近实时,ACID语意,支持快照语回溯等特性,吸引的不少开发者。刚才的介绍,大家也看到了,OPPO的选择是Iceberg,其中最重要的是支持CDC的近实时特性。但是近实时的特性在我们做业务推广是,却显得有些鸡肋。离线场景,小时任务可以满足大部分场景的时效要求。实时场景 ,对退化为成本更低的近实时,业务上对延时很难接受。

图5 Iceberg实时化

为了实现Iceberg的实时化,我们对它做了一些技术改进,下面分两个场景介绍。

场景一:是数据库的CDC入湖场景,需要支持数据变更。大数据领域,解决数据实时写入问题,通查会使用LSM结构。因此我们在架构上引入了Parker,一个支持分布式LSM的KV,在Iceberg前,承担数据缓冲。KV的引入,对基于主键的upsert也能够得到比较好的支持。

场景二:基于手机埋点的数据上报,每天的数据上报量非常庞大,万亿级别。这条链路中,使用了大量的Kafka资源。我们实时数仓的链路,Kafka的数据存储周期是T+3 ~ T+1天,这个过程中,我们选择通过Iceberg,使用效率更高的列式存储,降低Kafka的存储水位,使Kafka的数据存储周期变为T+3小时。既保障实时性,同时又降低Kafka存储成本。

3. 云数融合调度

OPPO每年30%的算力增长,评估下来,2022年大概有8w核算力缺口。如果不外采,算力缺口是否有补齐途径。有平台经验的伙伴,一般都了解,白天,通常是在线业务高峰。而夜间,往往离线计算会把集群计算资源打的很满,白天的负载,通常在50%左右。实现潮汐调度,在线、离线算力融合,是我们的必然选择。

图6 融合调度

实现算力融合,我们并没有完全走云原生的路径,计算资源完全由K8S调度。因为YARN的调度逻辑比K8S简单,对于大数据任务资源频繁释放回收的场景,效率上远高于K8S。因此,我们选择了YARN+K8S的调度逻辑,在K8S上实现yarn-operator。任务高峰,有K8S给大数据集群释放资源,过了高峰期,则自动回收。

云数融合调度中,大家可能会担心一个问题,就是容器释放的算力,性能上是否能够满足计算要求。这里可以得大家看下我们的一些测试。测试对比项是物理机、SSD容器,SATA容器,VM容器。从测试中可以看到,同等配置条件下,物理机性能最好,SSD容器和SATA容器性能次之。VM上的容器性能下降的比较厉害。所有,SSD容器和SATA容器性能损耗,是可以接受的。

image (32).png
云数融合调度中,大家通常会面临一个问题,就是如何稳定保障计算引擎的Shuffle效率。我们使用的是OPPO自研Shuffle Service。OPPO自研Shuffle Service 的初衷,是为了降低大任务的Shuffle失败率。我们的平台推出计算账单后,时不时会有用户因为Shuffle失败,希望我们减免计算费用。因为要知道Shuffle跑失败的任务通常规模不会小,费用可能是成百上千元。从平台的角度,当然不希望任务失败,就减免费用。云数融合中,Shuffle Service也起到了很好的作用,远程的Shuffle 服务,有效降低了本地存储压力,在资源扩缩容过程中,也能够保障计算稳定。

图7 Remote Shuffle Service

这里,可以给大家,看一下Shuffle Service的测试数据。这是TPC-H ,1TB数据下的测试结果。Shuffle Service 并不是说对所有的SQL任务,都能提高执行效率。但对Q16,Q21这样的大任务,效率提升还是非常明显的。 平均下来,大概有16%左右的提升。

图8 Shuffle Service性能测试结果

4. 数据湖存储

OPPO的数据存储,经历了三个阶段。

阶段一:全HDFS存储。 阶段二: 引入对象存储 。阶段三: 自研ADLS数据湖存储。

阶段一到阶段二,主要是将数据通过数据资产平台的周期设定,在达到某个时间点后,自动作为冷数据迁移到对象存储。阶段二到阶段三,则是统一文件,对象存储,由升级后的文件系统解决元数据瓶颈,冷热温分层存储。自研存储,关键技术有多协议适配,分布式元数据,扁平命令空间加速,多级缓存等。下面我逐一做下介绍。

图9 文件目录树

文件系统提供的是层次命名空间视图,整个文件系统的逻辑目录树分成多层,如上图所示,每个元数据节点(MetaNode)包含成百上千的元数据分片(MetaPartition),每个分片由InodeTree(BTree)和DentryTree(BTree)组成,每个dentry代表一个目录项,dentry由parentId和name组成。在DentryTree中,以PartentId和name组成索引,进行存储和检索;在InodeTree中,则以inode id进行索引。使用multiRaft协议保障高可用性和数据一致性复制, 且每个节点集合会包含大量的分片组,每个分片组对应一个raft group;每个分片组隶属于某个volume;每个分片组都是某个volume的一段元数据范围(一段inode id ); 元数据子系统通过分裂来完成动态扩容;当一分片组资源(性能、容量)紧接临近值时,资源管理器服务会预估一个结束点,并通知此组节点设备,只服务到此点之前的数据,同时也会新选出一组节点,并动态加入到当前业务系统中。

单个目录支持百万级别容量,元数据全内存化,保证优秀的读写性能,内存元数据分片通过snapshot方式持久化到磁盘以作备份及恢复使用。

图10 扁平目录缓存

而对象存储提供的是扁平命名空间;以访问objectkey为/bucket/a/b/c的对象为例,从根目录开始,通过”/”分隔符层层解析,找到最后一层目录(/bucket/a/b)的Dentry,最后找到的/bucket/a/b/c对于的Inode,此过程涉及多次节点间交互,层次越深,性能较差;因此我们引入PathCache模块用于加速ObjectKey解析,简单做法是在PathCache中对ObjectKey的父目录(/bucket/a/b)的Dentry做缓存;分析线上集群我们发现,目录平均大小约为100,假设存储集群规模在千亿级别,目录条目也才10亿个,单机缓存效率很高,同时可通过节点扩容来提升读性能;在同时支持"扁平"和"层次"命名空间管理的设计,与业界其他系统相比,CBFS实现得更简洁,更高效,无需任何转换即可轻松实现一份数据,多种协议访问互通,且不存在数据一致性问题。

图11 多级加速

数据湖架构带来显著的收益之一是成本节约,但存算分离架构也会遇到带宽瓶颈和性能挑战,因此我们也提供了一系列访问加速技术:

一. 多级缓存能力

第一级缓存:本地缓存,其与计算节点同机部署,支持元数据和数据缓存,支持内存、PMem、NVme、HDD不同类型介质,特点是访问时延低,但容量少。

第二级缓存:分布式缓存,副本数目弹性可变,提供位置感知能力,支持用户/桶/对象级的主动预热和被动缓存,数据淘汰策略也可配置。

多级缓存策略在我们的机器学习训练场景有不错的加速效果。

二. 谓语下推操作

另外存储数据层还支持了谓语下推操作,可显著减少存储与计算节点间大量的数据流动,降低资源开销并提升计算性能;

数据湖加速还有很多细致的工作,我们也在持续完善的过程中。

5. 展望

最后,结合刚才提到的三点技术方向,说下我们未来的一些规划和展望。

批流一体的计算,我们做到了元数据统一,存储统一。计算引擎统一,是可以积极探索的方向。虽然以 Flink 为代表的计算引擎,不断地宣称自己能做到批流一体,但是从实践角度,一个系统想做得多,往往不能再每个方向上都做到极致。统一的计算引擎我持保留意见,但不排斥这个方向的探索。这点上,我个人更倾于在批、流和交互式计算引擎上有一个公共层,通过这个公共层屏蔽不同引擎带来的适配成本,而非在引擎层实现完全的计算统一。

云数融合调度,目的是实现资源弹性,目前主要通过定时机制实现。因为我们知道业务资源利用规律,把这样的规律通过规则配置到我们弹性策略中。但是,弹性调度应该是更敏捷型,更灵活的,系统可以感知负载情况,自动进行资源的释放和回收。因为日常业务中会经常会有大规模任务重跑,任务突增等情况。这种情况下,灵活自主的扩缩容策略会对我们的业务有更好的帮助。

存储方面,刚才我们提到的冷、热、温分层存储目前还需要用户来定义。如某张事实表数据多久变冷存,某张维表是否一直需要热缓存加速。随着业务的变化,冷数据可能变成热数据,也需要手动做参数调整。其实,数据冷、热、温的划分,可以根据动态监测到的一些指标数据,通过算法自动地进行标识,转化,以达到不同数据使用不同存储介质,进而拥有更合理的存储成本。

最后还想说一点,数据平台我们会持续与云的融合。近年来广泛讨论的 Snowflake ,将数据仓库搬到云上,同时支持多云部署,非常有代表性。我们的产品和能力嫁接到云上,可以更广泛的输出我们的服务。

作者简介

Keung Chau OPPO数据架构负责人

负责 OPPO 数据平台的建设与技术演进。

获取更多精彩内容,扫码关注[OPPO数智技术]公众号