ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

大数据架构云上迁移:存储计算分离、弹性伸缩与湖仓一体落地指南

大数据架构云上迁移:存储计算分离、弹性伸缩与湖仓一体落地指南

大数据架构这几年最明显的变化,不是换了个更强的计算引擎,而是底层运行环境从物理机房一步步挪到了云上。我自己的经历就是这样一个过程:最早维护的是一批自建集群,三十多台机器,每天光处理“谁又写坏了一张表”就要花掉半个上午。后来逐步把离线数仓、实时链路和数据服务都搬到了某云厂商的托管平台上,架构从固定集群变成了存储与计算分离的弹性体系。这条“大数据领域数据架构的云计算融合之路”,听起来像是厂商宣传词,真正走下来才发现,它背后涉及存储底座、计算引擎、元数据、调度、治理、成本一整套决策。

写这篇东西,我想把这条路上最关键的设计思路和踩坑记录讲清楚。适合正在做传统数仓迁移、准备把数据平台云化、或者刚接手云上数据架构的同行参考。不管你是想全量迁到托管平台,还是只把冷数据先丢到对象存储上腾出集群空间,这里面提到的底层逻辑和实操细节大概率都用得上。

1. 数据架构为什么一定要往云上走

1.1 传统架构的三大天花板

传统的大数据平台,绝大多数长这样:一批物理服务器,本地磁盘组成分布式文件系统,计算引擎和存储服务跑在同一批节点上,也就是常见的存储计算一体化模式。这种架构在业务规模和团队规模都不大的时候很顺手,因为拓扑简单,安装部署一套开源组件就够用了。但业务一旦涨起来,三个问题会越来越明显。

第一个是存储和计算强绑定。集群里的每个节点既要承担数据存储,又要跑计算任务。扩容的时候你想多加点计算能力,不好意思,存储也跟着膨胀了;你想多存点数据,计算资源的浪费又躲不开。最尴尬的是,数据量和计算量并不是同比例增长的。某个业务线数据翻倍但计算需求不变,你依然得整体加机器,成本被强行抬了一倍。

第二个是资源利用率低。传统集群通常按业务峰值采购,平时 30% 左右的平均利用率很常见。白天跑报表、晚上跑批量任务,看起来忙得不可开交,但凌晨两点的计算资源可能空着一大半。做运维的都有体会,所谓“峰值容量”在大多数时候都是账面资产,真实产出很低。

第三个是运维成本失控。大数据组件的运维并不轻松,NameNode 要操心,任务队列要操心,磁盘故障要操心,版本升级要操心。一个小型集群七八套组件,随便哪个出了兼容性问题,排查时间都是按天算的。我见过不少团队,一半的人力消耗在“修车”上,留给数据建模和业务分析的时间少得可怜。

把这三大天花板放在一起看,问题的根源就清楚了:传统架构把存储、计算、运维三者焊死在一起。云计算的到来恰好提供了拆开这三者的机会。

1.2 云计算融合解决的核心问题

云计算和大数据融合,本质上不是把 Hadoop 搬到云服务器上重新跑一遍,而是把存储、计算、元数据、调度这些原本绑在一起的组件拆开,分别放到最适合的云服务形态里。

第一个改变是存储独立出来。对象存储成为底层的统一数据底座,容量几乎无限,按实际存储量付费,不再有“磁盘满了要加节点”的焦虑。数据湖里的原始数据、数仓里的加工结果、临时中间结果,都可以放进去。计算集群不再需要为存储容量买单,数据躺在对象存储上,计算集群销毁重建都不影响数据。

第二个改变是计算弹性伸缩。计算引擎可以独立于存储之外动态扩缩容。业务高峰时拉起几十个计算节点处理批量作业,低谷时缩到个位数甚至为零。这种弹性在传统架构下想都不敢想,因为缩容意味着数据没地方放,扩容意味着存储跟着翻倍。云上把这两个维度解开之后,资源利用率的提升非常明显。

第三个改变是托管服务大幅降低运维负担。云厂商把底层基础设施、HDFS 之类的元数据服务、调度服务、监控告警都做成了托管产品。平台团队不再需要凌晨爬起来处理磁盘故障,可以把精力集中在数据模型、任务优化和数据质量上。用我同事的话说,从“运维工人”变成了“数据工程师”。

这里要澄清一个常见的误解:上云不等于所有组件全换掉。很多团队迁移的第一步只是把本地文件系统换成云上对象存储,计算引擎继续用熟悉的那套,照样能获得成本和弹性的收益。融合是渐进的,不是推倒重来。

1.3 目标架构的清晰画像

和几个团队聊下来,我认为一个相对成熟的云上数据架构,可以分成四层来看。

最底层是存储底座,以对象存储为主,承载数据湖和数仓的所有数据文件。第二层是弹性计算层,包含离线批处理引擎、交互式分析引擎、流处理引擎,它们共用底部的存储,按需启动和销毁。第三层是统一元数据与权限层,负责登记有哪些库表、Schema 怎么定义、谁能读谁能写,让多个引擎看到完全一致的表。最上层是数据服务层,提供标准 SQL 接口、BI 报表接口、数据 API,让业务方不用关心数据到底存在哪个桶、用什么格式。

这套架构里最值得关注的趋势是“湖仓一体”。数据湖负责低成本地存放全量原始数据,保留所有可能性;数据仓库负责把数据加工成高质量、可建模、可直接分析的结果。过去湖是湖、仓是仓,两套系统互相导数据,延迟高、口径还不一致。云上融合之后,底层是同一份数据、同一份元数据,湖仓的界限更多变成了逻辑层的加工方式,而非物理隔离。

把目标画像画清楚再动手,远比先买个集群再想怎么用要重要。架构设计的很多决定,比如存储格式、元数据方案、计算引擎选型,一旦铺开再改,成本会是原来的好几倍。

2. 云上数据架构设计中最关键的四个决策

2.1 存储底座选型:对象存储和分布式文件系统怎么取舍

很多人在云上做架构时,第一个纠结的问题是:继续用分布式文件系统,还是切换到对象存储。我的答案很简单:除非有强一致性和高性能随机读写的特殊诉求,否则首选对象存储作为统一底座。

我整理过一个简单的对比,放在团队里讨论用:

对比维度自建分布式文件系统云上对象存储
容量扩展需要加节点,受硬件限制近乎无限,按需使用
成本模型前期硬件投入大,闲置浪费按存储量和请求次数付费
计算耦合存储与计算强绑定存储和计算完全解耦
运维复杂度节点维护、副本恢复都要管托管化,基本不用操心
一致性强一致多数场景最终一致或强一致能力已完善
适合场景低延迟随机读写、在线服务海量数据的写入、批量读取、归档

切到对象存储之后,有个细节必须提前处理:小文件问题。对象存储的元数据规模虽然远大于本地文件系统,但单位请求是有成本的,大量小文件会让后续的查询和写入都变得很慢。我们的经验是尽量把文件控制在单个 128MB 到 1GB 之间,通过合适的写入并行度、分区策略和小文件合并任务来保证。

还有一个容易忽略的点是请求费用。对象存储的计费通常包含存储容量费用和 API 请求费用,查询一个小表如果动不动就全表扫描,LIST 请求量会非常夸张。我在实际项目中就见过某团队一个月请求费高过存储费的情况,后来靠分区裁剪和压缩列式存储才压下来。

2.2 计算引擎组合:批处理、交互式分析、流处理别混为一谈

计算引擎是云上数据架构里最容易“选择困难”的部分。原因很简单,没有一款引擎能在所有负载下都做到最优。合理的做法是区分场景,让合适的引擎干合适的活。

离线批处理适合处理海量数据的定时加工,典型场景是每日全量跑批、复杂的多表关联、大规模聚合计算,这类负载对延迟不敏感,更看重吞吐和稳定性。交互式分析面向分析师和运营人员,追求秒级到分钟级的响应速度,这类负载并发不一定高,但查询模式高度不可预测。流处理则面向实时链路,关注秒级延迟和状态管理能力,用于实时 ETL、实时指标统计、异常检测。

我在选型时通常会用一个表格把需求框住:

负载类型典型场景关键指标弹性策略
离线批处理日跑批、全量加工吞吐、稳定性批量拉起计算节点,任务结束释放
交互式分析Ad-hoc 查询、报表响应时间、并发数常驻小集群 + 高峰自动扩容
流处理实时 ETL、实时指标延迟、状态可靠性按流量动态调整任务并行度

计算引擎选好后,资源隔离和配额管理比引擎本身更影响体验。云上多团队共用同一个数据平台很常见,如果不在队列级别做隔离,一个团队跑了个大查询,整个平台的资源都会被拖垮。我的做法是重要的生产链路单独占一个队列,带配额上限;探索性分析放到另一个队列,允许共享但限制最大并发。

2.3 统一元数据与权限:让所有引擎看到同一张表

传统大数据架构里,元数据往往是“各管各的”。Spark 认一套 Hive 元数据,Flink 有自己的 catalog,BI 工具又直连一套,最后同一张业务表在不同系统里有好几个版本,口径对不上是家常便饭。

云上融合之后,核心动作是把元数据统一到一个中心位置。这个位置可以是一个托管元数据服务,也可以是某种自带元数据管理的表格式方案。它的职责很清晰:定义库表结构、记录分区信息、保存 Schema 演进历史、维护数据文件的物理位置。所有引擎都通过同一个入口获取表结构,读到的自然就是同一张表。

统一权限模型同样重要。传统架构的权限散落在各个引擎里,HDFS 一套、Hive 一套、BI 一套,维护成本极高。云上可以实现集中授权:人员通过目录和命名空间看到允许访问的库表,列级权限可以控制敏感字段,行级权限能限制特定部门只能看自己的数据。这一步做扎实了,后面做数据安全合规会省非常多的事。

统一元数据落地有一个比较常见的弯路:只做了元数据同步,没有做权限打通,结果用户还是通过旧入口访问数据。我的建议是不破不立,一次性把访问入口切换到统一平台,旧入口保留只读窗口期,但业务必须迁走,否则永远存在两个口径。

2.4 数据治理在云上变得更具体了

数据治理这个词在传统数仓里已经被说得有点虚,但在云上数据架构里,它反而落到了一堆具体的机制上。

先说数据分层。上云之后 ODS、DWD、DWS、ADS 这套分层不仅没有过时,反而更好实现。ODS 层直接落到对象存储的原始区,保留全量历史不做任何加工;DWD 层做清洗、去重、标准化,以明细表的形式存在;DWS 层做轻度汇总,支撑大部分报表查询;ADS 层按业务主题高度定制,给应用系统调接口。每一层的存储位置、生命周期、负责人可以在云平台上用标签和目录清晰标注出来。

再说生命周期管理。对象存储天然支持生命周期策略,冷数据可以自动沉降到低频访问存储,归档数据甚至可以转成更低成本的介质。我在项目里给日志类数据设过 30 天降冷、90 天归档的策略,存储成本直接降了六成,而且全程不用人肉操作。

数据血缘和数据质量在云上也比自建环境容易做。任务跑完自动记录上下游关系,出了问题能反向定位影响面;质量规则以批任务的形式挂在表上,每天跑完后发布异常告警。建议从第一天就开始积累血缘和规则数据,等到数据量大了再补,成本会高到你想放弃。

3. 一个云上数据平台从0到1的落地过程

3.1 先把存量盘清楚再动手

很多迁移项目失败,不是因为技术选型有问题,而是没搞清楚自己有多少资产要搬。存量盘点这一步怎么强调都不过分。

盘点清单至少要包含这几个维度:现有集群规模(节点数、CPU、内存、存储总量)、核心任务清单(任务类型、负责人、执行频率、平均耗时)、数据依赖关系(表之间的血缘、上下游链路)、SLA 要求(哪些任务必须在几点前出数)、以及历史资源使用曲线(高峰期时段、峰值资源量)。

盘点结果会直接决定迁移策略。如果现有逻辑大部分是标准 SQL 加工,那迁移以改写和适配为主,成本相对可控;如果大量任务依赖特定语言的 UDF 或自定义组件,就要考虑重构或者保留部分自建集群;如果数据源特别杂乱,反而应该借迁移机会做一次数据治理,把源头口径统一一下。

我自己习惯把迁移分成三个阶段:并行期、切换期、稳定期。并行期新老平台同时跑,以新平台为准进行数据比对;切换期把一个又一个业务链路切到新平台,并且保留回退方案;稳定期跑两个月,确认数据和任务都没有问题后,再下线旧集群。节奏宁可慢一点,也不要让业务陪着你一起冒险。

3.2 数据入湖与数仓建模的实操过程

数据入湖的第一步是搭好存储路径规范。我在项目中用的是这种风格:

  • 原始数据区:/lake/ods/{业务域}/{数据源}/{表名}/dt={日期}/
  • 明细数据区:/lake/dwd/{业务域}/{主题}/dt={日期}/
  • 汇总数据区:/lake/dws/{业务域}/{主题}/dt={日期}/
  • 应用数据区:/lake/ads/{应用名}/{表名}/dt={日期}/

路径本身就是元数据的一部分,看到路径不用查别的系统就能判断数据属于哪一层、哪个业务域、哪个时间分区。这个习惯建议从一开始就建立,后期治理会顺畅很多。

数据同步方面,离线批量任务我一般用可断点续传的同步框架,每天定时把业务库数据拉进 ODS 层;实时链路则通过变更数据捕获(CDC)技术把数据库变更流近实时投递到消息中间件,再由流处理引擎写到对应的明细表里。两种方式覆盖了“准实时”和“全量离线”两类典型需求。

建模时要注意分区字段和文件大小的平衡。按天分区是最常见的选择,但有些高吞吐的表建议按小时分区,避免单分区文件数量过多。每个分区下文件的个数需要估算,目标是把前文提到的小文件问题消灭在设计阶段。

写入方式和文件格式我会优先选择列式存储(比如 Parquet 或 ORC),压缩使用高压缩比的算法,能显著减少存储成本和查询 IO。表的主键和排序字段设计也要在写入前定好,因为后续的合并操作和查询裁剪都依赖于这些元数据。

3.3 调度与任务迁移的实操顺序

调度系统是数据平台的“中枢神经”,上云时这块最容易低估工作量。调度系统选型要考虑的点包括:是否支持复杂的 DAG 依赖、失败重试和告警策略做得怎么样、有没有版本管理和回放机制、权限控制是否满足多团队使用、以及是否能够与云平台资源系统联动。

自建调度和云上托管调度各有优势。自建调度的好处是灵活、不受厂商限制,但稳定性、可观测性、升级维护都要自己负责;托管调度省心,但定制空间有限。我见过一些团队直接把开源的调度系统部署在云服务器上,再把计算资源池做成弹性伸缩的,体验和成本都不错。

任务迁移的顺序,建议按依赖关系自底向上。先迁那些没有上游依赖、输出稳定的基础任务,再迁中间层加工任务,最后迁顶层的报表和应用接口任务。每迁一个任务,都要在新旧平台跑同一份数据,比对输出行数和数值结果,直到完全一致为止。

资源参数的设置没有一劳永逸的答案,但可以给个起点参考:单任务并行度先按数据量除以单分区文件大小来估算,内存按任务复杂度上调一档。不要一上来就追求极限性能,稳定性永远是第一位的。跑两周后再根据实际耗时和失败率做针对性调优。

3.4 成本预算与容量规划的计算示例

上云最大的好处是成本从资本支出变成运营支出,但这也意味着如果你不看账单,成本会悄悄失控。先看容量估算怎么做。

假设某业务每天新增 100GB 数据,保存 90 天,加上两份副本冗余,那么纯存储空间大约是:100GB × 90 × 3 = 27TB。再考虑临时文件、计算结果和冗余,建议预留 30TB 到 40TB。这个量级对对象存储来说没有任何压力,但对传统 HDFS 来说已经是十几块大盘子的规模。

计算资源的估算要看任务并发度。假设高峰时段有 200 个任务同时在跑,平均每个任务需要 4 核 8GB 内存,那么基础计算需求是200 × 4 = 800核、200 × 8 = 1600GB内存。加上调度占用的弹性缓冲,建议预留 1000 核、2TB 内存。云上的计算资源按量付费或者预付费包年包月都行,关键是别把所有任务都堆在一个队列里。

成本构成通常包括四个部分:存储费用、计算费用、数据请求费用、以及可选的托管服务费用。前两项占比最大,也很好预估。特别留意跨域数据传输费用,在架构设计阶段就应该把数据链路尽量限制在同一个区域内,否则跨域流量会带来一笔不小的开销。

我还建议从迁移第一天就建立分账机制,给每个业务部门打上独立的项目标签。这样月底账单出来,哪个部门的数据最贵一目了然,成本治理才不会变成“大锅饭”。

4. 融合落地中那些坑,我替你们蹚过了

4.1 小文件爆炸:看不见的成本杀手

云上数据平台最容易踩的坑就是小文件爆炸。它的症状很典型:存储文件数量从几十万涨到几百万,元数据服务压力倍增,查询变慢,甚至整个平台的读写性能都跟着下降。

小文件产生的原因有很多。常见的有:Spark 动态分区写入时并行度设置过高,每个任务写出来一小撮文件;CDC 实时任务为了低延迟频繁提交,产生的增量小文件;还有反复 update 操作留下的旧版本文件没有及时清理。

解决思路分两条线。一条线是控制产生,写入的时候合理设置分区和并行度,让单个文件尽量接近目标块大小。另一条线是定期合并,通过离线合并任务把指定分区下的小文件重写成大文件。现在一些开源数据湖表格式自带小文件合并机制,开启后能明显缓解这个问题。

我的教训是:不要等文件数量异常了才做合并。把它当成日常运维的一部分,每周跑一次全量小文件统计,超过阈值就自动触发合并。稳定比什么都重要。

4.2 并发写冲突与数据一致性

在自建环境里,数据一致性问题通常被 HDFS 的文件系统语义掩盖了一部分。到了云上对象存储,多任务同时写一张表的时候,如果没有额外的锁机制保护,很容易出现互相覆盖或者读到半成品数据。

我遇到过最典型的一次,两个离线任务凌晨同时写同一张结果表,A 任务先写了 1 点到 3 点的分区,B 任务又把整个表的分区文件重写了一遍,第二天早上报表数字对不上,排查了整整一个上午。

解决方案有几个层次。最基础的是靠调度约束,保证同一张表的写入任务串行执行;再进一步是用支持事务的数据湖表格式,它可以在并发写时做乐观锁控制,写入失败会自动回滚;还有一个硬性纪律是所有离线写入统一走同一个写入程序,不允许分析师直接用临时脚本写生产表。宁可流程繁琐一点,也要保证数据一致性。

排查这类问题有个笨但有效的方法:每天跑一个数据质量校验任务,对关键表的记录数、关键指标值做“今日 vs 昨日”的波动监控。数值波动超过阈值就自动告警,及时发现问题。

4.3 弹性伸缩策略失灵:弹性不是魔法

不少团队刚上云时都以为开启了自动伸缩就万事大吉,结果发现高峰期任务照样排队,低峰期成本也没降多少。这里的关键在于弹性伸缩的粒度、阈值和冷启动时间没有设计好。

第一个坑是冷启动时间。云上的计算节点拉起需要几分钟,如果业务流量是突发的,等节点就绪时业务高峰期已经过去了一半。我的做法是保留一部分常驻资源池,只对增量部分做弹性扩容,这样既能覆盖突发流量,又不至于全部依赖冷启动。

第二个坑是伸缩阈值设置。阈值设得太灵敏,任务一多就扩容,成本飙升;设得太迟钝,扩容跟不上需求,延迟依然存在。建议按队列维度分别设定:核心生产队列预留容量,允许小幅波动;探索分析队列可以缩到很小,响应慢一点大家也能接受。

第三个坑是只扩不缩。有些平台伸缩策略里扩容条件写得很完善,缩容条件却很粗糙,导致资源一直维持在高水位。一定要检查缩容策略,设置一个低于扩容阈值的回缩区间,并配合任务的峰谷曲线测试几轮。

4.4 成本失控与平台绑定担忧

成本问题的核心不是云厂商收费贵,而是传统团队习惯了“一次性采购”的成本感知,对“按量付费”的持续账单没有概念。很多项目第一个月的账单会比预想高 20% 到 30%,原因是不少人把任务都配置成了高规格资源,跑完了也不释放。

解决成本失控的第一步是打标签分账。每个任务、每个存储桶、每个队列都要有明确的归属方,月底按标签汇总出成本报告。第二步是清理僵尸资源。那些三个月没跑过的任务、没更新过的临时表、孤立的存储桶,该删就删。第三步是定期做资源规格降配,把那些一直按高规格跑但实际根本用不满的任务降一档,成本立刻下来。

平台绑定担忧也是真实存在的。我的应对方法是两层:底层数据文件尽量用统一的开源格式,存储路径自己可控;上层接口尽量走标准 SQL 和标准数据源接口,避免深度依赖某个云平台独有的服务。这样即使将来要换平台,也只是把数据重新灌到另一个存储上,不需要重写全部任务。

5. 往下一步走:Serverless、湖仓一体和可观测性

5.1 Serverless 化是弹性的终极形态

云上数据架构的下一个明显趋势是 Serverless 化。计算资源不再以常驻集群的形式存在,而是按查询或者按作业动态分配,跑完就释放。好处是资源利用率理论上可以接近完美,坏处是性能稳定性和成本可预测性需要重新设计。

实际使用中,Serverless 模式特别适合两类场景:一类是负载波动大、有明显的忙闲周期的业务;另一类是临时性的探索分析,几分钟算完就走。对于每天固定时间跑批的核心链路,我反而建议保留预置容量的模式,给核心链路留足稳定性空间。

5.2 湖仓一体继续深化

湖仓一体不是一个静态概念,它还在快速演进。早期湖仓一体的重点是解决“湖和仓的数据打通”,现在已经变成了在数据湖上直接构建完整的数仓能力:事务支持、Schema 演进、增量读取、流批一体加工,都在湖上原生完成。

落地时我会重点关注三类能力:一是 UPSERT 能力,能不能高效地处理更新和删除;二是增量读取能力,下游能不能只取新增变化的数据而不是全表重扫;三是统一表格式管理,多引擎写入同一个表时的一致性保障。这三点做到了,湖仓一体才算真正投产。

5.3 从“平台可用”到“平台可观测”

融合之后的平台要长期健康运行,必须建立一套贯穿成本、质量、性能、安全四个维度的观测体系。也就是说,团队每个人都能回答出来:跑一个任务要花多少钱、数据质量有没有异常、资源瓶颈在哪、谁在访问什么敏感数据。

我的习惯是每个周末用一个小脚本汇总四个维度的数据,生成一份简洁的平台运营周报:任务成功率和重试次数、资源实际使用率、成本周环比变化、关键表质量校验结果。这份周报不需要写给所有人看,它是自己判断平台健康度的仪表盘。只要坚持三个月,平台的问题基本都会浮出来。

最后聊一点个人体会。做数据架构这些年,我发现上云最值钱的不是省了多少成本,而是把工程师从“救火队员”的角色里解放了出来。过去我们花大量精力应对机器故障和组件问题,现在可以把这些时间投入到数据模型设计、业务分析与性能优化上。融合之路没有终点,每隔一段时间,新的存储介质、新的计算模式、新的治理理念都会出现,但只要抓住“存储与计算解耦、元数据统一、弹性伸缩、成本可观测”这几条主线,方向就不会错。对于正准备上云的团队,我的建议是先小范围试点一条核心链路,把坑都踩一轮,跑顺了再全面铺开,千万别一上来就搞大迁移。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进