2. AWS数据存储与计算服务选型

批流一体架构的选型,本质上不是“挑一个最强服务”,而是把数据从产生到消费的全链路拆成存储层、计算层、调度层三个平面,再判断每个 AWS 服务在这三个平面中承担什么角色、边界在哪里。S3、Kinesis、MSK、Glue、EMR、Lambda、Flink 这七个服务经常被放在一起比较,但它们并不在同一层:S3 是存储底座,Kinesis 与 MSK 是流式接入与传输通道,Glue 与 EMR 是批处理与元数据主力,Lambda 是事件驱动的小颗粒计算,Flink 则是真正的流批统一计算引擎。选型的第一步,是先把它们放回各自的位置。

存储层:S3 是批流一体的共同底座

在批流一体架构中,S3 几乎总是数据湖的落点。流式数据经 Kinesis 或 MSK 接入后,通常仍要落到 S3 形成持久化分层(如 raw、cleansed、curated),批处理再基于 S3 上的分区数据做重算与回填。S3 的关键参数不是“存多少”,而是对象键设计与分区策略:例如按 dt=2025-03-01/hour=08/ 组织前缀,可以让 Athena、Glue、EMR 在扫描时只读取必要分区,显著降低扫描量与成本。S3 本身不提供计算,但它通过事件通知(ObjectCreated)触发 Lambda、Step Functions 或 Glue 作业,成为调度层的天然触发源。因此存储层选型结论很明确:S3 作为唯一持久化真相源,Kinesis 与 MSK 只做传输,不做长期存储。

接入与传输层:Kinesis 与 MSK 的分工

Kinesis Data Streams 是托管型、按分片(shard)计费的流式通道,适合与 Lambda、Firehose、Flink 直接集成,运维负担低。MSK 则是托管 Kafka,适合已有 Kafka 生态、需要多消费者组、长保留期、复杂 topic 治理的场景。两者在批流一体中的角色差异可以用“接入复杂度”和“消费灵活性”两个维度判断:如果团队没有 Kafka 运维经验、数据量中等、消费方以 AWS 原生服务为主,优先 Kinesis;如果已有 Kafka 客户端、需要跨系统复用同一份流、或要求消息保留数天以上,优先 MSK。需要注意,Kinesis 单分片写入上限为 1 MB/s、读取 2 MB/s,分片数不足会直接表现为 ProvisionedThroughputExceededException,这是选型时必须预估的容量参数。

计算层:Glue、EMR、Lambda、Flink 的边界

计算层是选型最容易混淆的地方。Glue 是 Serverless Spark 与元数据目录(Data Catalog)的组合,适合中小规模 ETL、爬虫式 schema 推断、以及需要快速起停的批作业;EMR 是可控集群,适合大规模、长时运行、需要自定义 Spark/Hive/Presto 参数与实例类型的重批处理;Lambda 适合事件驱动、单次执行 15 分钟以内、数据量小的轻量转换或触发;Flink 则适合有状态流处理、窗口聚合、Exactly-Once 语义、以及希望用同一套 SQL/DataStream 代码覆盖流与批的场景。一个实用的判断顺序是:先看延迟要求(秒级还是小时级),再看状态复杂度(是否需要窗口、join、状态后端),最后看团队运维意愿。若三者都指向“流式、有状态、低延迟”,Flink 是首选;若只是“每天跑一次、数据在 S3 上”,Glue 或 EMR 更经济。

批流一体架构中的服务分层与选型判断 存储层 · 持久化真相源 Amazon S3 raw / cleansed / curated 分区 Glue Data Catalog 表结构 / 分区元数据 S3 Event Notification 触发下游计算 接入与传输层 · 流式通道 Kinesis Data Streams 分片计费 · 原生集成 · 低运维 Amazon MSK Kafka 生态 · 多消费组 · 长保留 Kinesis Firehose 微批投递至 S3 / Redshift 计算层 · 批 / 流 / 事件驱动 AWS Glue Serverless Spark 中小批 ETL Amazon EMR 可控集群 Spark/Hive 大规模重批 AWS Lambda 事件驱动 · ≤15 min 轻量转换 / 触发 Apache Flink 有状态流处理 窗口 / Join / Exactly-Once 调度层 Step Functions 编排 · EventBridge 定时/事件 · Glue Workflow · MWAA(Airflow) 触发源:S3 事件、Kinesis 到达、MSK topic、Cron 表达式

调度层:把触发与编排分开看

调度层常被忽略,但它决定了批流一体能否真正“自动跑起来”。触发源通常有三类:S3 对象到达、流式通道有数据、时间窗口到达。编排工具则负责把多个计算任务串成 DAG,并处理重试、依赖与失败告警。Step Functions 适合状态机式的复杂编排,EventBridge 适合定时与事件路由,Glue Workflow 适合纯 Glue 作业链,MWAA 适合已有 Airflow DAG 的团队。选型时不要把所有调度都塞进 Lambda,Lambda 适合做“触发器”,不适合做长流程编排。

一个可落地的初步选型示例

假设业务场景为:电商订单事件实时写入,需要秒级风控指标,同时每天凌晨对全天订单做一次营收重算。可以这样选型:接入层用 Kinesis Data Streams(4 个分片,预估峰值 3 MB/s),实时计算用 Flink(消费 Kinesis,做 1 分钟滚动窗口聚合,结果写回 Kinesis 供风控消费),同时 Firehose 将原始事件投递到 S3 的 raw/orders/dt=.../hour=.../;批处理用 Glue 每天凌晨读取 S3 分区,做营收重算并写入 curated/revenue/;调度用 EventBridge 定时触发 Glue Workflow,S3 事件触发 Lambda 做小文件合并。这个组合中,MSK 和 EMR 没有被选中,原因是当前规模不需要 Kafka 生态,也不需要对集群做深度调优。选型不是“谁更强”,而是“当前阶段谁更合适”。

判断顺序建议:先定延迟(秒级→流,小时级→批),再定状态复杂度(有窗口/Join→Flink,无状态→Glue/Lambda),最后定运维意愿(不想管集群→Serverless,需要深度调优→EMR/MSK)。

选型时最容易踩的三个坑

  • 把 Kinesis 当存储用。Kinesis 默认保留 24 小时,最长 365 天,但按存储计费且不提供分区扫描能力,长期数据必须落 S3。
  • 用 Lambda 做重 ETL。Lambda 单次 15 分钟上限、内存与临时磁盘有限,遇到大文件或复杂 join 会超时,应改用 Glue 或 EMR。
  • 忽略 Glue Data Catalog 的共享价值。Catalog 是 Athena、EMR、Glue、Redshift Spectrum 的共同元数据入口,建表时统一分区命名,能避免后续跨服务重复定义 schema。

把七个服务放回存储、接入、计算、调度四个位置后,选型就变成了一道有约束条件的匹配题:S3 固定为底座,Kinesis 与 MSK 二选一或并存,Glue、EMR、Lambda、Flink 按延迟与状态复杂度分工,调度层用 Step Functions 或 EventBridge 收口。下一阶段再根据数据量、SLA 与成本做参数级调优,而不是在选型阶段就追求“全都要”。