离线作业300+,凌晨3点告警把我叫醒——任务调度怎么治理?
先说结论
调度治理的核心是三件事:① 理清DAG依赖关系(该依赖的要依赖,不该依赖的要解耦);② 作业分级分优先级(不是所有作业都同等重要);③ 做好幂等设计(失败重跑不会出错)。
最常见的调度问题不是'调度工具不好用',而是'DAG设计不合理'。依赖关系过深、不必要的强依赖、没有超时设置——这些才是凌晨告警的根源。
幂等设计是基本功:任何作业,不管重跑多少次,结果必须一样。INSERT OVERWRITE天然幂等,INSERT INTO不幂等——这是最容易踩的坑。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
数仓做到一定规模后,调度就成了最大的运维痛点。我在某短剧出海公司,离线作业从50个涨到300+,DAG依赖越来越复杂,凌晨3点告警是家常便饭。有一次核心ROI报表因为上游一个不重要的作业失败导致级联阻塞,业务方早上8点打开报表还是空的——那次之后我们下决心做了一次调度治理。今天把治理方案和避坑经验全讲出来。
DAG依赖设计:强依赖 vs 弱依赖
调度治理的第一步是理清依赖关系。我们把依赖分成三种:
| 依赖类型 | 定义 | 失败时行为 | 典型场景 |
|---|---|---|---|
| 强依赖 | 上游必须成功才能运行 | 阻塞等待 | DWD依赖ODS、DWS依赖DWD |
| 弱依赖 | 上游最好成功,但失败也能运行 | 跳过继续运行 | ADS依赖辅助维度表 |
| 无依赖 | 跟上游没有数据关系 | 独立运行 | 不相关的业务域的作业 |
我们治理前的最大问题是'过度依赖'——很多不必要的强依赖导致级联阻塞。比如ADS层的ROI报表强依赖了一个'内容标签维度表'的更新任务。这个维度表每周才更新一次,但被配成了每天强依赖。某天这个维度表的更新脚本有bug跑失败了,ROI报表就被阻塞了——但ROI报表根本不需要每天最新的内容标签。
// 治理前的DAG依赖(过度依赖)
ods_ad_click -> dwd_ad_click -> dws_channel_roi -> ads_roi_report
^
dim_content_tag --------+ <- 不必要的强依赖!
内容标签跟ROI没关系
// 治理后的DAG依赖(解耦)
ods_ad_click -> dwd_ad_click -> dws_channel_roi -> ads_roi_report
dim_content_tag -> dws_content_analysis -> ads_content_report (独立链路)
作业分级:P0/P1/P2
不是所有作业都同等重要。我们把300+作业分成三级:
| 级别 | 数量 | SLA | 失败处理 | 典型作业 |
|---|---|---|---|---|
| P0 核心 | ~30个 | 上午8点前完成 | 自动重试3次+立即电话告警 | ROI报表、收入报表、大屏数据 |
| P1 重要 | ~100个 | 上午10点前完成 | 自动重试3次+群通知 | 渠道分析、用户画像更新 |
| P2 一般 | ~170个 | 下午2点前完成 | 自动重试3次+邮件通知 | 历史趋势报表、周报数据 |
// 作业分级配置示例
// P0作业配置:
// priority: HIGH
// retry_count: 3
// retry_interval: 5min
// timeout: 60min(超时即告警)
// alert_channel: 电话 + 企微群 + 短信
// SLA_deadline: 08:00
// P1作业配置:
// priority: MEDIUM
// retry_count: 3
// timeout: 120min
// alert_channel: 企微群
// SLA_deadline: 10:00
// P2作业配置:
// priority: LOW
// retry_count: 3
// timeout: 180min
// alert_channel: 邮件
// SLA_deadline: 14:00
分级的关键价值:P0作业的资源优先级最高,调度引擎优先分配资源给P0。当集群资源紧张时,P2作业可以排队等待,但P0作业必须立即运行。这避免了'一个不重要的作业占用大量资源导致核心报表超时'的问题。
幂等设计:重跑不出错
幂等是调度治理的基本功——任何作业重跑N次结果必须一样。看起来简单,但很容易踩坑:
-- 幂等写法:INSERT OVERWRITE(重跑会覆盖,结果一样)
INSERT OVERWRITE TABLE dws_channel_roi_1d PARTITION(dt='${bizdate}')
SELECT channel, country_code, SUM(pay_amount) AS revenue
FROM dwd_user_payment_di WHERE dt='${bizdate}'
GROUP BY channel, country_code;
-- 非幂等写法:INSERT INTO(重跑会重复插入!)
INSERT INTO TABLE dws_channel_roi_1d PARTITION(dt='${bizdate}')
SELECT channel, country_code, SUM(pay_amount) AS revenue
FROM dwd_user_payment_di WHERE dt='${bizdate}'
GROUP BY channel, country_code;
-- 重跑一次:数据翻倍!重跑两次:数据翻三倍!
-- 如果必须用INSERT INTO,先DELETE再INSERT
-- 在Hive中用INSERT OVERWRITE + 分区来实现
-- 在Doris/Hologres中先DELETE WHERE dt=xxx再INSERT
面试高频追问
追问一:你们用什么调度工具?为什么选它?
我们在短剧出海公司用的是DataWorks(阿里云自带),在出海硬件品牌用的是Airflow。选择标准:如果全套阿里云技术栈(MaxCompute/Hologres),DataWorks是最省事的——跟阿里云服务原生集成,不需要自己搭建和运维。如果是开源技术栈(Spark/Hive on AWS),Airflow是社区最活跃的选择——Python写DAG灵活度高,但需要自己运维Airflow集群。DolphinScheduler也是好选择,国内社区活跃,适合中大型团队,但学习曲线比Airflow陡。
追问二:上游任务失败了,下游自动重跑时怎么保证数据正确?
靠幂等+依赖检查。上游成功重跑后,调度工具会检测到上游状态变成'成功',自动触发下游运行。因为下游是INSERT OVERWRITE(幂等),不管运行几次结果都一样。但有一个陷阱:如果上游重跑后数据变了(比如修了一个bug,数据量从100万变成120万),下游必须也要重跑——不能只重跑上游不重跑下游,否则下游还是基于旧数据。我们的做法是:P0链路上游重跑后,自动级联重跑所有下游。
追问三:怎么处理跨天运行的长任务?
这在大数据量场景很常见——凌晨0点开始跑,2点还没跑完,第二天的调度已经开始了。我们的策略是:① 每个作业设超时时间(P0作业60分钟,超时即告警排查);② 长任务拆分成多个子任务并行执行(比如按国家分区并行处理);③ 调度层面设置互斥锁——同一个作业不允许两个实例同时运行,后一个实例必须等前一个完成后才开始。
实战踩坑
调度治理中最痛的一次经历:某天凌晨4点,P0的ROI报表因为依赖链路太长(5层深度,ODS→DWD→DWS→中间表→ADS→推送Hologres),其中一个中间层的Spark作业因为数据倾斜跑了3个小时还没完成。等全链路跑完已经上午11点了——业务方等了3个小时。
后来我们做了两个优化:① 缩短关键链路深度——把5层压缩到3层,去掉了不必要的中间表(直接在DWS里做了之前中间表的逻辑);② 给每一层设置超时阈值——如果DWD在凌晨2点前没完成,跳过DWS的常规链路,直接用昨天DWS的数据+今天的增量做快速合并出ADS,保证8点前有数据(虽然可能不是最精确的)。
// 关键链路优化:降低DAG深度
// 治理前(5层,端到端3-4小时)
ODS -> DWD -> DWS -> tmp_roi_detail -> ADS -> Hologres推送
30min 40min 60min(倾斜!) 20min 10min
// 治理后(3层,端到端1.5小时)
ODS -> DWD -> DWS(含原tmp逻辑) -> ADS+推送
30min 50min 20min
// 降级方案(保底)
如果DWS在02:00前未完成:
-> 触发降级任务
-> 用昨天DWS + 今天增量ODS快速合并出ADS
-> 数据可能有1-2%误差,但保证08:00前有数据
总结
调度治理的三板斧:理清DAG依赖(解耦不必要的强依赖)、作业分级(P0/P1/P2差异化SLA)、幂等设计(INSERT OVERWRITE天然幂等)。面试时讲调度,不要只说'我们用Airflow/DataWorks'——要能说出你管理多少个作业、怎么分级、遇到过什么调度事故以及怎么优化的。调度治理不是技术难题,是工程管理能力的体现。
调度管好了,但数据质量出问题才是最致命的——下游报表全错了。下一篇聊数据质量监控体系怎么建,包括质量规则、告警机制和数据血缘。
你们有多少离线任务?凌晨被告警叫醒过吗?最长的任务跑多久?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长