批处理架构核心要素:数据源、计算引擎、调度系统、存储系统、监控告警
聊批处理架构,说白了就是搭一套能稳定跑、出了问题能快速定位的系统。我这些年做过的批处理项目,从几十个任务的小集群到上千个任务的平台,核心要素其实就五个:数据源、计算引擎、调度系统、存储系统、监控告警。缺一个,后面就等着踩坑吧。
你想想看,数据从哪来?谁来算?谁安排什么时候算?算完放哪?出错了怎么知道?这五个问题回答清楚了,架构就稳了。
核心观点:批处理架构不是把组件拼起来就行,而是要让这五个要素形成闭环。数据源负责接入,计算引擎负责处理,调度系统负责编排,存储系统负责持久化,监控告警负责兜底。缺了任何一个,系统都是瘸腿的。
数据源:批处理的起点
数据源是批处理的第一道关卡。我见过太多项目,架构设计得漂漂亮亮,结果数据源一接入就崩了。为什么?因为没搞清楚数据源的特性。
批处理的数据源,常见的有这么几类:
- 数据库:MySQL、PostgreSQL、Oracle 等。注意,批量读取时别用 select *,要分页或使用游标,不然 OOM 等着你。
- 消息队列:Kafka、RocketMQ。批处理从消息队列拉数据,要控制好拉取频率和批次大小。
- 文件系统:HDFS、S3、本地文件。CSV、Parquet、Avro 格式最常见。
- 日志系统:Flume、Filebeat 采集的日志。
- API:第三方接口或内部服务。
我的经验:数据源接入时,一定要做数据源适配层。什么意思?就是抽象出一个接口,不管底层是数据库还是文件,上层计算引擎看到的都是一样的数据格式。这样换数据源时,改个实现类就行,不用动业务逻辑。
我曾经在一个项目中,数据源直接从 MySQL 全表扫描,每天几千万条数据,跑了一个小时还没读完。后来改成分批读取 + 并行拉取,十分钟搞定。嗯,这里要注意:数据源的读取方式,直接影响整个批处理的吞吐量。
计算引擎:批处理的心脏
计算引擎是批处理的核心。选型时,我一般看三个维度:
| 引擎 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| MapReduce | 离线大规模数据处理 | 成熟稳定,生态完善 | 慢,中间结果写磁盘 |
| Spark | 迭代计算、SQL 分析、机器学习 | 内存计算,速度快,API 丰富 | 内存管理复杂,调优门槛高 |
| Flink | 流批一体,实时计算 | 低延迟,Exactly-Once 语义 | 批处理场景不如 Spark 成熟 |
| Hive/Tez | SQL 化批处理 | 类 SQL,学习成本低 | 复杂逻辑表达能力有限 |
我个人习惯是:如果团队 SQL 能力强,优先选 Spark SQL 或 Hive。如果要做复杂的 ETL 逻辑,Spark Core 或 Flink DataStream 更灵活。你想想看,选错了引擎,后面改起来成本极高。
避坑指南:我曾经在一个项目中选了 Flink 做纯批处理,结果发现 Flink 的批处理模式当时还不成熟,任务调度开销大,小文件处理慢。后来换回 Spark,问题迎刃而解。所以,不要为了技术炫酷而选型,要看实际场景。
调度系统:批处理的指挥官
调度系统负责安排任务什么时候跑、跑在哪、失败了怎么办。没有调度系统,批处理就是一盘散沙。
常见的调度系统有:
- Azkaban:轻量级,适合中小规模任务
- Airflow:DAG 编排能力强,社区活跃
- DolphinScheduler:国产,可视化好,支持多租户
- Oozie:Hadoop 生态老牌调度器,但配置繁琐
- 自研调度:大厂常见,定制化程度高
调度系统的核心能力,我总结为三点:
- 依赖管理:任务 A 跑完才能跑任务 B,这是基本要求。
- 失败重试:网络抖动、资源不足导致的失败,自动重试 3 次。
- 资源控制:别让一个任务把集群资源吃光,其他任务饿死。
关键点:调度系统一定要支持任务优先级。我遇到过线上紧急数据需要优先跑,结果被一堆日常任务堵着,等了两个小时。从那以后,我设计的调度系统都强制要求任务带优先级标签。
存储系统:批处理的家
数据算完了,放哪?存储系统的选型,直接影响查询性能和成本。
批处理存储系统,我一般分三层:
| 层级 | 技术选型 | 用途 |
|---|---|---|
| 临时存储 | HDFS、本地磁盘 | 中间结果、临时文件 |
| 结果存储 | Hive 表、Parquet 文件 | 最终计算结果,供下游使用 |
| 服务存储 | MySQL、Elasticsearch、ClickHouse | 对外提供查询服务 |
我个人建议:结果存储优先用列式存储格式(Parquet、ORC),查询性能比行式存储高 5-10 倍。服务存储要看查询场景,点查用 MySQL,分析查询用 ClickHouse。
我的习惯:存储系统一定要做数据生命周期管理。比如临时数据保留 7 天,结果数据保留 30 天,历史数据归档到冷存储。不然磁盘满了,整个批处理都跑不动。
监控告警:批处理的守门员
监控告警是最后一道防线。没有监控,系统出问题了都不知道。我见过一个团队,批处理跑挂了三天,业务方找上门才发现。嗯,这很尴尬。
监控告警要覆盖四个维度:
- 任务维度:任务是否成功、运行时长、资源消耗
- 数据维度:数据量是否异常、数据质量是否达标
- 系统维度:CPU、内存、磁盘、网络
- 业务维度:产出时间是否延迟、结果是否符合预期
告警策略上,我一般这么配置:
- 任务失败告警:立即通知,级别 P0
- 任务超时告警:超过预估时间 1.5 倍,级别 P1
- 数据量波动告警:相比昨天波动超过 30%,级别 P2
- 资源使用率告警:超过 80%,级别 P2
避坑指南:我曾经设置过过于敏感的告警,结果一天收到几百条告警,团队直接麻木了,真正的问题反而被淹没。后来我调整策略:告警要分级,P0 必须立即处理,P2 可以白天再看。告警不是越多越好,而是越精准越好。
五个要素如何协同
五个要素不是孤立的,它们需要协同工作。我画了一张流程图,展示典型的批处理数据流转:
流程很简单:调度系统触发任务,从数据源拉取数据,交给计算引擎处理,结果写入存储系统,整个过程由监控告警覆盖。但实际落地时,每个环节都有坑。
举个例子:调度系统触发任务时,如果数据源还没准备好,任务就会失败。所以调度系统要支持数据就绪检查。计算引擎处理时,如果数据倾斜,一个节点跑完其他节点还在跑,要加数据重分区。存储系统写入时,如果并发太高,要加写入限流。监控告警要能自动关联,比如任务失败时,自动拉取当时的日志和资源使用情况。
总结一下:批处理架构的五个核心要素,每个都很重要。但更重要的是它们之间的协同关系。数据源不稳定,调度系统要能重试;计算引擎慢,存储系统要能缓冲;监控告警发现问题,要能自动触发修复流程。这才是成熟的批处理架构。