本节摘要:高级调度处理时间表无法表达的就绪:上游表晚到、跨 DAG 窗口对不齐、长等待占槽、按数据而不是按钟触发。Dataset 把产出与消费写成数据契约;传感器与可延迟算子把等待从盲轮询里救出来;分支与事件触发让图在运行时裁剪路径。目标是少瞎跑、少占槽、失败原因仍读得懂。
阅读完本节,你应当能够:
原文把高级调度概括成防御与数据感知两条螺旋。环境契约——数据是否落地、配额是否够、上游是否在发版——必须进入放行条件。否则调度器只会在两点整点火,两点四十七分数据才到,任务失败重试,把抖动写成事故。
Dataset(2.4 引入的数据感知)允许任务声明产出某个数据集 URI,下游 DAG 声明消费它。上游成功更新数据集后,下游获得触发。这比双方硬对 execution_date 更接近业务语言:“这张表的这一窗写完了”。代价是血缘要设计:一个数据集被多个上游更新,下游会被触发多次;映射任务每个分区都更新,可能打出一串碎触发。我倾向整窗完成才更新一个数据集。
ExternalTaskSensor 仍有用:对方不是 Dataset 体系、或必须等对方某个具体 task_id。关键是窗口对齐,用正确的 execution 偏移。对不齐时传感器超时,看起来像网络故障。
# 概念:下游 DAG 消费上游声明的数据集 # 上游任务 outlets 指向同一数据集 URI # 下游 schedule 跟随数据集而不是只跟 cron
时间表与数据集可以同时存在:每天有一个最早启动时刻,同时必须数据就绪。只写数据就绪、上游当天失败,下游会一直安静——要有超时告警,否则“没跑”比“红了”更难发现。
| 手段 | 主用途 | 主要代价 |
|---|---|---|
| 时间表 | 闭合账本 | 数据晚到会空跑或失败 |
| Dataset | 表写完再跑 | 碎触发与静默不跑 |
| 传感器 | 等对方任务 | 对钟与占槽 |
| API 触发 | 外部事件 | 必须带业务日 |
| 可延迟等待 | 长等待还槽 | 要有 Triggerer |
传统传感器按 poke_interval 醒来看一眼,期间仍占 Worker 槽。等待集群创建、等待对象存储大文件,会把执行器槽位变成停车场。Deferrable Operator 把等待交给 Triggerer,Worker 去干别的活。原文用“长轮询不再阻塞 Worker、利用率显著上升”来描述它的动机。
什么时候必须 deferrable:等待经常超过一分钟,且并发等待多。什么时候可以 poke:几秒的本地文件、开发环境。Sensor 超时时间要短于业务 SLA,超时是 failed 还是 reschedule,要写进规范,避免无限 poke。
REST API 触发 DAG Run,把外部事件变成一次带 conf 的运行。适合“文件到达通知已经由对象存储事件发出”。不要用 Airflow 自己每分钟 list 桶。事件在外面做,Airflow 做编排。schedule=None 的 DAG 专吃这类触发。
分支算子按函数返回选择下游。未选中路径 skipped。汇聚规则改 none_failed,否则整天卡在 skipped。分支是运行时裁剪,不是动态长出环。复杂到分支里再分支,图会不可读,把决策下沉到任务内部或拆 DAG。
depends_on_past、传感器、Dataset、每分钟调度叠在同一条链上,没人能在故障时说出“为什么没跑”。选一个主触发:时间、数据、或外部 API,其余当校验。校验失败应明确 failed,而不是静默不建 Run。
⚠️ 常见坑:用 ShortCircuit 或分支“跳过”失败,让总览变绿。审计会以为窗口成功。失败就要红,跳过只留给真正的业务可选路径。
💡 关键直觉:高级调度增加的是放行条件的表达力,不是让调度器变聪明到猜你的表好了没有。表好了必须有信号:数据集、传感器、或 API 触发。
池与优先级在高峰期比再加一个传感器有用。关键 DAG 高优先级、回填低优先级。高级调度解决就绪,不解决争抢。争抢是配额。
跨时区、跨夏令时的事件触发,仍要给 Run 一个逻辑日期。事件时间与业务窗口可能差一天,conf 里带上业务日,任务读 conf,不要读触发瞬间的日历。
TriggerDagRunOperator 启动另一张图,适合明确的扇出。要防止循环:A 触发 B、B 再触发 A。无环约束在单 DAG 内由解析保证,跨 DAG 触发要靠人肉规范或命名约定。
每条 DAG 在 doc_md 里写一行:主触发是时间、数据集、还是 API。评审看到三个都写,就打回。时间适合闭合账本;数据集适合“上游表是真相”;API 适合外部系统已经做了事件。传感器是校验或过渡,不是第三个主触发。depends_on_past 是滚动约束,也不是主触发。把角色写混,故障时无法问“今天该不该有 Run”。
碎触发治理:映射任务不要每个 index 都更新数据集。在汇聚任务上更新一次,表示整窗完成。下游 timeout:数据就绪 DAG 必须有“过了某时刻仍未触发”的监视,可用时间表加一个最晚检查任务,或平台级的“应到未到”扫描。静默是数据感知调度最大的治理成本,比多跑一次更危险。
分支与 ShortCircuit 的审计:跳过必须是业务可选,不能用来把失败变绿。失败就 failed。合规审计会抽窗口,绿而空的窗口是伪证。原文把高级调度说成契约协调者,契约里必须包含“何为成功”。跳过失败不是成功。
TriggerDagRunOperator 扇出时写死对方 dag_id,禁止用变量拼出任意 id 去触发生产图。循环检测靠命名与评审:谁可以触发谁,画一张跨 DAG 图,环就否决。单 DAG 无环检查管不到这一层。
按业务对象加窗口粒度,不要按任务名。任务会改名,对象更稳。URI 是契约,不是文件路径——即使看起来像对象存储地址,也不要在文档里写成可点击的外链路径去诱导复制。团队内部约定一种字符串格式即可。多个上游写同一 URI 要非常小心,等于多个工位按同一个到位灯,灯亮的含义会变脏。
不一定更快完成业务,但更省槽位。墙钟可能差不多,集群能同时等的事情变多。若你只有几个短传感器,改 deferrable 的收益可能小于多一个 Triggerer 进程的运维。用占用槽位的时间积分来决定,不要用“高级”来决定。
先量传感器超时与对齐错误的工单量,确认痛点是对钟而不是外部真的晚到。然后在上游汇聚点声明一个数据集,下游改消费,两边暂时保留传感器作校验。并行跑一段时间,对比触发时刻。稳定后去掉传感器,补“应到未到”监视。一步切会在静默周让报表消失。数据集不是开关,是迁移。迁移期文档写双触发如何去重,避免同一窗跑两次。max_active_runs=1 可当去重。REST 触发的 DAG 不要再挂时间表当主触发,否则事件与钟会抢。主触发唯一,是 5.1 贯穿始终的纪律,迁数据集时最容易破戒。
API 触发必须带逻辑日期或业务日,放在 conf。任务读 conf,不读触发瞬间。事件晚到一天,仍应入正确的账。缺身份字段的事件触发,会把迟到事件记成“今天”,对账永久偏一天。这是高级调度里最贵的一类静默错误,因为状态全绿。绿的是错账。Dataset 触发同样要定义窗口身份:数据集更新携带哪一窗。携带不清,下游会用触发时刻当窗。时间表 DAG 混用事件时,身份冲突要在文档里写清谁赢。谁赢写不清,max_active_runs=1 只能防止并行,不能防止错窗。错窗比并行更难发现。发现时数据已经对外。对外之后再补,是 2.1 的 backfill,但信任损失补不回来。所以 5.1 把身份字段当成高级调度的第一字段,而不是把 Dataset 当第一名词。名词不能入账。字段才能。
6.3 可以断言 doc_md 含“主触发”字样,或断言 schedule 与数据集不同时乱配。乱配规则由平台定义:例如声明了数据集消费则禁止再设过密 cron。断言做不到完美,但能挡住最糟的双钟。双钟是 5.1 的原罪。原罪导致说不清为何没跑。说不清则监控的应到未到无法落地。无法落地则静默。静默比红更危险。危险要用声明对抗。声明写进 doc_md。doc_md 进结构测试。结构测试进 CI。CI 进合并。合并后主触发唯一。唯一才能设计监视。监视才能值班。值班才能让数据感知调度成年。成年之前,传感器对钟虽然土,但理由清楚:等到超时就红。红比静默好。好土开过好静默的巧。巧要配监视。监视要声明。声明要测试。测试在本节提出,在 6.3 落地。落地前,人工评审看一行主触发。一行没有,打回。打回是 5.1 的牙齿。牙齿保护可解释性。可解释性是高级调度的第一产出。产出不是更多触发方式。方式多为互斥。互斥靠声明。声明靠一行。一行靠打回。打回几次,作者会自己写。自己写比培训快。培训会忘。打回会记。记性在合并失败里。失败很烦。烦出唯一主触发。唯一之后,Dataset 才允许。允许不是默认。默认仍是时间表。时间表最好解释。解释优先于时髦。时髦是事件。事件要身份字段。身份字段在上一节。上一节加本节,构成 5.1 的完整纪律:身份加唯一。两者都有,灯才能亮。灯亮而可解释。可解释才能进生产。生产不要神秘调度。神秘调度会催重启。重启救不了没声明的主触发。声明救。声明结束。
应到未到监视没落地前,关键链允许保留对齐正确的 ExternalTaskSensor。土但会红。红比静默好。好土写进声明:过渡,截止日期,监视替代条件。条件没满足不准拆传感器。不准拆是牙齿。牙齿防止为了 Dataset 名词拆掉唯一会叫的等待。会叫比优雅重要。优雅在监视之后。之后才拆。拆的步骤仍是并行期对比触发时刻。对比没有,不准切。不准切结束时髦事故。时髦事故结束于静默周。静默周结束报表。报表结束信任。信任用土保护。保护写进声明。声明结束 5.1 对土的尊重。尊重结束唯新。唯新结束。主触发仍唯一。唯一结束双钟。双钟结束。可解释结束神秘。神秘结束重启。重启结束。本节结束于土的合法。合法结束。
下一节处理谁能看见图、谁能读密码、谁能触发生产。