talabat构建跨AWS与Google Cloud的近实时分析架构
DataHot 速览
talabat是中东北非领先的生活服务应用,截至2025年12月拥有超过700万月活跃用户,并于2024年12月在迪拜金融市场上市。作为Delivery Hero的子公司,其业务数据横跨AWS与Google Cloud两大云平台。本文介绍了talabat如何构建混合多云湖仓,在AWS上维护单一Apache Iceberg数据副本,同时在GCP上实现受治理的近实时分析。该架构同时应对跨云与跨区域挑战,为多云数据平台建设提供了参考。
为什么值得关注:跨云湖仓与近实时分析是数据平台领域的关键实践,该案例展示了如何在双云环境下保持数据一致性与分析时效性,值得数据从业者关注。
本文目录 14 节
译文
AI 逐段翻译talabat 是中东和北非(MENA)地区领先的日常应用,为客户提供便捷、个性化的方式,从众多餐厅和零售商处订购食品、杂货和其他日常必需品。talabat 于 2004 年在科威特成立,业务已扩展至阿拉伯联合酋长国、阿曼、卡塔尔、巴林、约旦、伊拉克和埃及,截至 2025 年 12 月,每月活跃客户超过七百万。talabat 总部位于阿拉伯联合酋长国迪拜,并于 2024 年 12 月成功在迪拜金融市场(DFM)完成首次公开募股。作为 Delivery Hero SE 的子公司,talabat 利用全球专业知识不断提升服务、拓展业务版图并推动创新。凭借强大的合作伙伴和骑手网络,talabat 将客户与他们所需的东西连接起来,随时随地满足需求——为整个地区提供日常便利。
在本文中,我们展示了 talabat 如何构建一个混合多云 lakehouse,在 AWS 上保留流数据的单一 Apache Iceberg 副本,同时支持从 Google Cloud Platform (GCP) 进行受治理的近实时分析。
talabat 的数据
数据是 talabat 业务的神经系统。从客户点击“下单”的那一刻到门铃响起的瞬间,talabat 的系统会做出瞬间的、数据驱动的决策,即时优化定价、调度、路由和订单安全。多年来,talabat 的应用已发展成横跨两个公有云的环境。我们的事务性和运营骨干在 AWS 上成熟,工程团队在此构建和运营服务。与此同时,大量分析师、数据科学家和数据分析工程管道在 Google Cloud Platform 仓库 Google BigQuery 上标准化。
这两项投资都很深入,且都带来价值。因此,战略问题不是“我们整合到哪个云”,而是“如何让数据在两个云之间干净地流动”。这一框架决定了后续的一切。挑战不仅涉及跨云,还涉及跨区域,AWS 服务托管在欧盟区域,而数据位于 GCP 美国区域。
下图展示了 talabat 的数据如何在 AWS 上的运营平面和 GCP 上的分析平面之间流动。

图 1:AWS 运营平面与 Google Cloud 分析平面之间的数据流
历史上,数据工程团队编排两个云之间的数据移动,强制从 AWS 物理迁移到 GCP,从欧盟到美国。使用传统的提取、转换和加载(ETL)工具和框架进行迁移,导致数据经过多次跳跃而延迟和重复:Amazon Relational Database Service (Amazon RDS) 到 Amazon Simple Storage Service (Amazon S3) 欧盟 AWS 区域,Amazon S3 欧盟到 Amazon S3 美国区域,最后 Amazon S3 美国到 BigQuery 美国。
每一步跳跃都是一次复制,每次复制都加剧风险:多个故障点、累积延迟、冗余计算和存储、类型保真度,最重要的是跨区域和跨云的出口成本。
简而言之,旧设计花费了金钱、延迟和可靠性来解决它自己造成的问题:移动数据以便 BigQuery 能够读取。这是经典的数据仓库瓶颈。我们可以改用开放数据湖吗?可以。但分析使用严重依赖 BigQuery,这限制了通过开源数据湖层的访问。因此,重新设计从相反的前提开始:在 AWS 上保留一份副本,让 BigQuery 就地读取。这就是本文其余部分描述的:talabat 的 lakehouse。
挑战
运营系统持续发出业务事件流,如订单生命周期变更、供应商、菜单、物流和骑手信号,以及发布到 Apache Kafka 上的 Amazon Managed Streaming for Apache Kafka (Amazon MSK) 的支付信息。这些事件以 Protocol Buffers 编码,并通过在 Confluent Schema Registry 中注册的向后兼容模式进行管理,以便生产者和消费者可以安全地随时间演进。
分析方面的要求说起来简单,但实现起来困难:使这些事件在几分钟内可查询、类型正确,并且可从每个团队已使用的工具中查询。
将双云足迹视为技术债务很诱人。对于像 talabat 这样的实时业务,这仅仅是地形,每一方都发挥真正的优势:
- 事件骨干位于 AWS 上。我们的事务和流式系统发布到 Amazon MSK。消费和处理这些事件延迟最低、风险最小的地方是它们旁边,在同一个 AWS 区域中。
- 分析资产位于 Google Cloud 上。数千个下游模型和仪表板,以及构建它们的人员,都假设 BigQuery 作为查询界面。
整合任何一方都意味着多年的迁移和一组用户能力的显著回退,所有这一切都是为了消除摄取和分析之间的接缝。数据工程师决定设计这个接缝。设计目标变成了一句话:在 AWS 上保留一份物理副本,并从两个云原生读取它。混合数据 lakehouse 使“哪个云”问题成为访问路径细节,而不是架构分叉。
我们先尝试的方案:热路径上的跨云写入
我们的第一次尝试反转了我们最终交付的流程。原始(也称为 Bronze)层数据从 AWS 直接写入 Google Cloud Storage 上由 BigQuery 管理的 Iceberg 表。从理论上讲,这使数据最接近最大的消费群体。在实践中,在始终在线的流式路径上跨云写入引入了一类我们不想面对的问题:
- 摄取路径上的跨云依赖。每个微批次都与远程云写入 API 的可用性和延迟耦合。
- 流式写入API故障以摄取事件的形式暴露。远程写入成为脆弱环节,将读侧问题转变为写侧停机,这是最不宜承受问题的地方。
- 预览受限的功能限制了物理布局。某些分区行为和功能并非普遍可用,限制了我们在成本和性能方面组织数据的方式。
教训很明确:左移。写入路径应当短、本地化、直接。跨云关注点属于读取路径,在那里可以使其只读、缓存和重试,而不影响摄取。这种重新框定直接引导我们采用了今天运行的架构。
选择 BigQuery 如何读取 AWS 驻留数据
随着流程颠倒(原始数据在 AWS 上,从 Google Cloud 读取),我们评估了三种让 BigQuery 读取物理上位于 AWS 的表的方法。我们根据四个标准对每种方法进行了评估:
- 无数据移动。
- 开放的表格格式。
- 可治理的信任模型。
- 最小的运维面。
| 方法 | 评估 |
| 跨云写入 Google Cloud Storage | 继续将青铜层写入 Google Cloud Storage 上由 BigQuery 管理的 Iceberg。我们因前述原因拒绝了此方案:它在摄取热路径上引入了跨云依赖和跨区域延迟。 |
| BigQuery Omni | 通过 BigQuery Omni 的托管跨云计算查询 AWS 驻留数据。这引入了比只读青铜层所需更多的托管面和限制,而且我们希望直接拥有目录和信任模型。 |
| Lakehouse 联邦 Apache Iceberg REST 目录(由 IAM 认证) | 让 BigQuery 读取 Amazon S3 Tables(一项 Amazon S3 功能,提供托管的 Apache Iceberg 表),通过一个联邦目录,该目录同步 AWS Glue Data Catalog 元数据,并通过跨云 IAM 信任进行认证。这满足了所有四个标准,因此我们选择了它。 |
决定性特性是原始数据不离开 AWS,格式是开放的 Apache Iceberg(因此 Amazon Athena、Spark 和兼容 Iceberg 的引擎可以读取相同的表),并且跨云关系以身份和信任的形式表达,而非重复的复制任务。
为什么选择 Amazon S3 Tables
随着架构确定为在 AWS 上维护一份 Iceberg 副本,我们需要一个为大规模 Iceberg 专门构建的存储层。Amazon S3 Tables 满足了要求,同时未增加运维面。表维护(压缩、快照过期、未引用文件删除)作为服务管理的策略自动运行,避免了原本会随表数量线性增长的外部编排任务。同样重要的是,每个表都是 Amazon 资源名称(ARN)可寻址的资源。这意味着 IAM 策略可以授予或拒绝访问单个表,适用于我们应用于任何其他 AWS 资源的相同最小权限模型,且 AWS CloudTrail记录每个访问决策。对于完全通过 IAM 表达信任边界的跨云设计,表是一等 IAM 资源不是便利而是前提。S3 Tables 在单一构造中提供了托管的 Iceberg 后台维护和细粒度、可审计的访问控制,使工程团队可以专注于流逻辑,而不是底层的存储管道。
解决方案概述
系统分为两半,在开放的表格格式处交汇:
- AWS 上短且本地化的写入路径。
- 只读的跨云握手,使 BigQuery 能够消费数据。
唯一的事实来源是 Amazon S3 Tables 中的 Apache Iceberg 数据。每个消费者都读取这一个物理副本。
下图显示了端到端架构,从事件摄取到存储再到消费路径。

图 2:从事件摄取经存储到消费路径的端到端架构
写入路径:短、本地、可靠
我们在与 Amazon MSK 相同的 AWS 区域(eu-west-2)运行每个 Kafka 主题一个 Amazon EMR Serverless Spark Structured Streaming 作业(使用预构建的 Docker 镜像,emr-7.13.0,基于 ARM64/Graviton)。将计算与事件主干置于同一位置可最小化每个微批次传输的数据量,节省成本和延迟。每个作业运行 Spark 的 foreachBatch 操作,触发间隔约为一到五分钟,采用至少一次交付。每个微批次执行五个步骤:
- 消费来自 Kafka 的数据。
- 解码 Protocol Buffers,使用注册的 schema。
- 转换为目标 Iceberg schema。
- 追加到 Amazon S3 Tables 中的 Iceberg 表。
- 提交偏移量。
该循环不间断地重复。
此路径仅涉及 AWS。没有跨云依赖,只有一次有意的跨区域跳跃:欧洲(伦敦)区域(eu-west-2)的计算,美国东部(弗吉尼亚北部)区域(us-east-1)的存储。这产生了标准的 AWS 跨区域数据传输成本,这是一个有意的选择,以便 BigQuery 的跨云读取保持在相同区域内。
坏记录不会阻塞流。它们落入专门的死信队列(DLQ)表(<table>_dlq),位于单独的 S3 Tables 桶中,存储原始负载(raw_value_b64)和 skip_reason。不会静默丢弃任何内容。DLQ 表通过 Lakehouse 注册到 AWS Glue Data Catalog,以便工程师可以从 Amazon Athena 或 BigQuery 检查失败。
从此时起,Amazon S3 Tables 是事实来源。
关键点:跨云握手
这是设计的核心。BigQuery 通过 Lakehouse 联邦 Apache Iceberg REST 目录读取 S3 Tables Iceberg 数据,这是 Google Cloud 侧的只读目录,指向 AWS 驻留的表。三个机制使其工作。
- 开放的目录契约(Iceberg REST)。
Amazon S3 Tables 暴露了一个 Apache Iceberg REST 目录 接口,Google Lakehouse说的也是同样的标准。由于双方都同意 Iceberg 磁盘格式和 REST 目录协议,因此不需要转换层或数据复制。BigQuery 读取与 Athena 和 Spark 读取相同的 Iceberg 数据文件。在 Google Cloud 方面,这是一个单一的Lakehouse 联合目录。表以 talabat-data.s3tables-glue.catalog.orders 的形式呈现给分析师。- 跨云身份与信任(IAM 和 OIDC)。
Lakehouse 目录以 Google 管理的服务身份(Lakehouse REST 目录服务账号)向 AWS 进行身份验证,该身份被 AWS 身份和访问管理(IAM)角色通过 OpenID Connect(OIDC)与accounts.google.com联合信任,使用sts:AssumeRoleWithWebIdentity,并在角色的信任策略中固定了服务账号的数字 ID。对 S3 Tables Iceberg 端点的请求使用 SigV4 签名。这是任何 AWS SDK 使用的标准 AWS 请求签名方案,并限定于 S3 Tables 服务。换句话说,这种握手不是专有连接器。它是由可信外部身份执行的标准 AWS 请求签名。信任关系在 AWS 侧以基础设施即代码(IaC)形式编码:授予最低权限,并可在任何时候撤销。下图展示了这一认证序列。

图 3:Lakehouse 目录与 AWS IAM 之间的跨云认证序列
有关此信任关系的逐步演练,包括创建 IAM 角色、验证令牌的受众和主题、以及在信任策略中固定 Lakehouse 服务账号身份,请参阅 创建和管理 AWS Glue 联合数据集 和 设置 AWS Glue 的跨云 Lakehouse。
- 元数据同步 (约五分钟刷新)。
联合目录定期从前置 S3 Tables 的 AWS Glue 数据目录 同步表元数据。新创建的表和新数据在短暂的刷新周期(约 300 秒)内对 BigQuery 可见。读取针对实时 Iceberg 数据提供。仅同步目录指针。
结果是,在 AWS 上写入一次的表在 BigQuery 中作为普通目录对象出现,并可以使用标准 SQL 查询,而数据字节不会离开 AWS,格式保持开放。
基础设施即代码:跨云信任面
以下部分解释了架构图中显示的认证握手。Lakehouse 目录服务账号提供 Google OIDC JSON Web 令牌(JWT),AWS 通过 IAM OIDC 提供商验证该令牌,返回限定于只读 S3 Tables 访问的短期凭证。
resource "aws_iam_openid_connect_provider" "google" {
url = "https://accounts.google.com"
client_id_list = [var.lakehouse_sa_audience] #Lakehouse REST-catalog serviceaccount
}data "aws_iam_policy_document" "trust" {
statement {
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.google.arn]
}
condition {
test = "StringEquals"
variable = "accounts.google.com:sub"
values = [var.lakehouse_sa_subject_id] # nobody else can assume the role
}
}
}
resource "aws_iam_role" "lakehouse_read" {
name = "bq-lakehouse-read"
assume_role_policy = data.aws_iam_policy_document.trust.json
max_session_duration = 43200 # 12-hour sessions, then re-issued
}statement {
actions = [
"glue:Get*",
"s3tables:GetTable", "s3tables:GetTableData", "s3tables:ListTables", "s3tables:ListTableBuckets", "s3tables:GetTableMetadataLocation", "s3tables:ListNamespaces", "s3tables:GetNamespace","s3tables:GetTableBucket"
]
resources = [var.s3tables_bucket_arn, "${var.s3tables_bucket_arn}/*"]
}gcloud iceberg catalogs create s3tables-glue \
--federated-catalog-type=GLUE --glue-aws-region=us-east-1 \
--glue-aws-role-arn=arn:aws:iam::<account>:role/bq-lakehouse-read- 将 Google 注册为可信身份提供商。限定于我们的 Lakehouse 目录服务账号:
- 将信任精确定位到该唯一身份。这是安全关键点。该角色只能通过 Google 签名的令牌来承担,其主题必须与我们的服务账号匹配。对 sub 声明的条件将其他所有主体拒之门外:
- 授予只读最低权限。承担的角色仅拥有通过 AWS Glue 读取目录元数据和通过 S3 Tables 访问 Iceberg 数据的足够权限,完全由 IAM 策略保护,并且没有任何可写权限:
- Google 侧目录绑定到此角色。Lakehouse 联合目录本身是带外创建的(一次性 gcloud 调用),指向上述角色,以便每次读取都呈现该受信身份。AWS 密钥绝不会存在于 Google Cloud 中:
这四个步骤共同构成了整个握手:受信任的颁发者、仅我们的服务账号可以承担的角色、最低权限的读取授权,以及绑定到该角色的目录。
运营经验:将元数据视为一流关注点
跨云运营开放、联合目录教会我们将表元数据视为一流的运营关注点。在实践中,这意味着:
- 快照保留:保持较短的 Iceberg 快照保留期,以便每个表的元数据保持紧凑并可靠同步。
- 压缩:通过 S3 Tables 内置维护配置,将表维护(压缩和快照过期)标准化为统一、服务管理的策略。
- Schema 演进:当 Protobuf schema 演进(向后兼容的添加)时,Spark 作业在 S3 Tables 中的 Iceberg schema 中追加或删除列。联合目录在下一次同步周期中获取更改,BigQuery 无需手动干预即可反映更改。
这些是我们知道如何设置后的小而易于理解的设置,它们区分了简单工作的目录和漂移的目录。
消费数据是引擎的选择,而不是副本的选择
源上线后,同一个 Iceberg 表在一个物理数据集上以三种方式可用。
- 一个BigQuery 用户使用标准 SQL 查询,并连接到 Google Cloud 数据仓库的其余部分。
- 一个基础设施工程师在 Amazon Athena 中运行相同的查询,用于临时检查和持续集成(CI)验证。
- 一个数据科学家直接使用 Spark 读取表,路径中没有 BigQuery 或 Athena。
没有人等待夜间导出,也没有人协调三个不同副本。只有一个。
性能和成本影响
定性优势已经很明显:
- 分钟级新鲜度的原始数据,用于近实时分析。先前架构的延迟不是容量问题,而是设计约束。摄取每五分钟运行一次,但下游每小时批处理作业将端到端新鲜度限制在 60-90 分钟。通过目录联合,相同的数据在产生后几分钟内即可查询:95% 的事件在五分钟内,并且可以选择调整管道以覆盖 100% 的事件,适用于对延迟敏感或关键任务的工作负载。
- 一份存储在 S3 Tables 中的副本,三个计算引擎。BigQuery、Athena 以及 Spark 或其他兼容 Iceberg 的引擎读取 Amazon S3 Tables 中的单个物理 Iceberg 数据集,避免了重复存储以及保持副本同步的对账成本。
- 热路径上无跨云出口。摄取在 AWS 本地进行。唯一的跨云流量是读取时的元数据同步和查询读取,而不是持续的写入流。根据对月度 AWS 和 Google Cloud 数据传输费用、编排开销、多层 ETL 工作流成本和存储备份费用的内部比较,talabat 在相当的数据量下将数据移动成本降低了约 40%。该比较跨越了移除持续复制管道前后的两个月,这一改变消除了每月数百 TB 的重复跨区域和跨云数据传输。
- 开放表格式,无锁定。由于原始 bronze 数据层是 Amazon S3 Tables 中的 Apache Iceberg,数据不局限于任何单一查询引擎或云。新消费者通过使用 Iceberg 来采用它,而不是请求导出。
- 可治理的跨云访问。跨云边界通过 IAM 信任关系(最小权限、可审计、可撤销)来保障,而不是通过持续的数据管道。BigQuery 中的最终用户访问控制通过 GCP 中的原生基于角色的访问控制(RBAC)和联邦目录上的细粒度访问控制单独管理。
未来增强
展望未来,我们计划通过将剩余的高价值事件流和批处理存储接入到混合的一配置模式中,来扩大源覆盖范围。我们正在正式制定端到端的新鲜度目标及其可观测性:批次级指标、死信监控和目录同步健康。我们将继续调整快照保留和压缩,以便随着表数量的增长,跨云目录保持快速可靠。更广泛地说,我们打算让“一次写入,任何引擎读取”成为 bronze 层之外新数据的默认模式,进一步将开放表格式作为云服务提供商之间的连接组织。
结论
身处两个云通常被视为需要迁移离开的问题。对于 talabat 来说,这只是地形。事件骨干在 AWS 上占有重要地位,而分析社区则在 BigQuery 上运营。通过将带有 Apache Iceberg 的 Amazon S3 Tables 作为 AWS 上的单一事实来源,并让 BigQuery 通过由跨云 IAM 信任保护的 Lakehouse 联邦 Iceberg REST 目录以只读方式消费它,我们将双云约束转变为单个受治理的数据集,引擎可以在几分钟内读取。写入路径保持短、本地和可靠。跨云问题存在于读取路径上,这正是它应该存在的地方,以开放标准和身份来表达,而不是数据移动。
这就是握手:AWS 上的一份数据副本,一个开放的目录契约,以及一个签名的、可信的、可撤销的身份跨越云边界读取它。
本文重点介绍如何从 BigQuery 读取 AWS 驻留数据。对于更广泛的多云 Lakehouse 模式,包括将其他系统的目录联邦到 AWS Glue 数据目录中,请参阅面向代理式 AI 的 AWS 多云 Lakehouse 架构。
这篇内容对你有用吗?
反馈只用于改善内容筛选,不等同于收藏