开发者学堂课程【SaaS 模式云数据仓库系列课程 —— 2021 数仓必修课:DataWorks 调度配置最佳实战】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/55/detail/1057
DataWorks 调度配置最佳实战
内容简介:
1.调度基本介绍
2.依赖关系简介
3.依赖关系实战
1.调度基本介绍
(1)节点
节点是描述 DataWorks 数据分析和处理过程的基本单元。比如 Shell、ODPS SQL、ODPS MR、PyODPS 等,这些都统一称为节点任务。如下图在开发面板里面都能看到这些节点组件。
(2)实例
在 dataworks 的后台每天会按照用户配置调度的属性去进行周期性的调度,调度就是依赖每天生成的实例。实例是在前一天 23:30 的节点快照,统一生成的运行实例。对用户去配置调度的最大感触是如果在 23:30 之前去提交的调度的最大配置,那么会在 23:30 之后生效;如果是在 23:30 之后去配置调度的一些依赖关系,那么将会在隔天生成实例。
实例会对非天任务进行拆分,如一小时一次的小时节点将会拆分成具体的 24 个实例。
(3)调度规则
首先满足依赖关系:即上游节点必须完成,才能调度下游节点。也就是说上游的节点必须要返回成功,并且完成整个数据处理的过程,才能调度下游节点。
其次,下游节点能不能使用,还要判断定时时间是否已经到了,如果到了,立即执行。如果没有到,等待时间。
(4)依赖关系
依赖关系是描述两个或多个节点之间的语义连接关系,其中上游节点的状态将影响其他下游节点的运行状态,反之则不成立。如下图必须要完成上游节点才能运行下游节点,颠倒不成立。
(5)跨周期依赖
跨周期依赖其实分了跨周期及跨版本两个概念:
Ø 跨周期依赖是针对小时任务:即小时任务依赖同一天的上一个周期。
比如说一个节点是按照一个小时调度一次,那当前节点能否调度要依赖于上一个小时的节点是否调度完成。
Ø 跨版本依赖即跨天依赖:即依赖前一天的任务。
比如今天任务能否运行依赖于昨天的任务是否成功执行返回。
(6)自依赖
自依赖是天然的跨周期跨版本依赖:
Ø 针对天任务即依赖昨天的任务。
Ø 针对小时任务即依赖上一周期,每天第一个周期依赖昨天最后一个周期。
比如说凌晨一点的任务依赖于十二点的任务是否完成。
2.依赖关系简介
调度属性:冻结
(1)概念介绍
l 周期实例中的冻结只针对当前实例,且正在运行中的实例,冻结操作无实际效果,并不会kill掉正在运行的实例。
l 冻结状态的任务会生成实例,但是不会运行。若需要运行冻结的实例,您需解冻实例,单击重跑,实例才会开始运行。
(2)出错机制
如果开启了出错机制,则默认失败后重试3次,每次间隔2分钟。如果还是失败,则会进行当前节点失败的返回。
注:默认为“可以重跑”,当设置“不可重跑”时,节点运行一次成功后,该任务实例不可重跑。
调度周期分为分钟,小时,日,周,月。需要注意的是如果周期大于天的,由于调度的实例划分是按天生成的,所以周月任务在不运行的那一天实际是按照空跑处理的。若选择日调度,而且不勾选定时调度的,定时时间统一按照0点处理。
跨周期依赖里有四个选项:
1)不依赖上一调度周期
2)自依赖,等待上一调度周期结束,才能继续运行
3)等待下游任务的上一周期结束,才能继续运行
4)等待自定义任务的上一周期结束,才能继续运行
依赖项有三个选项:
本节点:即为自依赖,等待上一周期运行成功后才可执行。
自定义:可以选择本 project 或者其他 project 的节点作为依赖,即等待自定义节点上一周期运行成功后,才可执行。
一层子节点:依赖第一层子任务的上周期
当任务对之前的周期有依赖的时候,可以勾选依赖上一周期,然后根据自己的要求选择具体的依赖项。
这里普及一个概念,跨周期和跨版本,版本可以理解为一个业务日期,如果今天的任务依赖昨天任务即跨版本,今天的多个周期之间互相依赖,即跨周期,需要注意的跨周期依赖不能指定依赖具体哪个周期,只能依赖上一个周期!
(3)自依赖的使用
虚线即跨周期依赖,实线是正常的依赖。
3.依赖配置实战
(1)天任务依赖
天任务互相依赖,箭头表示数据流向,天定时任务相互依赖,上游未完成时下游即使定时时间到了也不运行。只有上游任务完成时,下游任务才会跑起。
比如说上游任务零点,下游任务零点或七点,整个流程都会依赖于规则和定时时间去执行。
天任务相互依赖,上游存在跨周期依赖,上游昨天的周期不成功则今天的任务不会运行,今天的下游任务一样被阻塞。
比如说14年12月31日的任务没有完成,那么依赖于这一天的15年1月1日的任务也不会去运行。
为天任务相互依赖,上游任务依赖于上一周期的一层子节点,上游昨天的任务未成功会同时阻塞昨天和今天的下游。
如图2014年12月31日两个任务有相互的依赖关系,2015年1月1日两个任务有相互的依赖关系,由虚线关系可以得出上游任务依赖于上一周期的一层子节点。
(2)小时任务依赖上一周期
小时任务依赖上一周期,只要一个周期未成功,后续所有周期都会阻塞,并且可以有效避免一个周期任务运行慢了导致后续周期定时到了之后并发运行。
比如说零点钟,五点钟,十点钟都有实例,零点钟的实例没有运行成功,那么后续两个任务都会被阻塞。
(3)小时任务依赖天任务
小时任务依赖天任务,待天任务完成后开始调度小时任务,定时时间已到的周期会并发开始执行。
比如说实例 B1,B2,B3 依赖于实例 A,实例 A 在每天的十二点跑起,实例 B1,B2,B3分别是零点,八点和下午四点的任务,那么这些小时会在等待天任务完成之后,再开始调度小时任务,并且在定时时间上并发执行。隔天再会生成相同的依赖关系,如15年1月1日。
(4)天任务依赖小时任务
天任务依赖小时任务,需要等小时任务的所有周期都完成才能调度天任务,即使天任务定时时间已经到了,但是小时任务还有周期未完成就不会被调度。
比如实例 A 是 实例 B1,B2,B3 下游的一个节点,依赖于上游三个节点,如果按照每八个小时跑一个任务,即实例 B1,B2,B3 都成功运行完成之后,实例A的定时时间已到,实例A的节点才会开始运行。
(5)小时任务依赖小时任务且周期数一样
父子都为小时任务,且周期数相同,则每个运行周期一一对应的依赖,下游定时若晚于上游定时,定时时间到了并不会调度,需要等上游对应周期运行完成才会开始调度。
比如说实例 A1 和实例 B1,实例 A2 和实例 B2 等的依赖关系,上游任务为小时任务,下游任务也为小时任务,并且两个小时任务的周期都为一个小时或者两个小时,生成的实例数一样,周期一样,这样就可以看作为父子节点,所有的 A 和 B 形成一一对应的关系。并且需要等八点运行的实例 A1 运行成功之后,六点的 B1 才会开始运行。
(6)小时任务依赖小时任务周期数不一样
小时任务依赖小时任务,且下游周期数大于上游周期数,会依据就近原则挂依赖(时间小于等于自己且不重复依赖)。
比如说上游按照每十二个小时运行一次,那么上游一天形成两个实例,下游按照每六个小时运行一次,那么下游一天形成四个实例,如果下游的实例数大于上游的,就会就近挂依赖,实例 B1 和 B2 在零点和六点就会挂依赖于较近的实例 A1 的零点
案例一:小时任务依赖天任务
之前案例讲到,如果上游天任务完成时下游有多个周期定时时间已到,会导致这些周期被并发调度起来,如果不希望下游并发调度起来,则需要将下游小时任务设置成自依赖,即依赖上一周期→本节点。需要注意的是,自依赖会依赖跨版本(跨天),如果昨天最后一个周期未完成,会导致今天的任务无法调度。
比如上游实例 A 是天任务,下游实例 B 是周期为八小时的小时任务,在实例 A 完成之后,实例 B 根据虚线顺序逐步完成,在红色框框内是一个跨天的依赖关系,2015年1月1日零点的实例 B1 不仅要依赖于实例 A 的完成,也要依赖于上一周期实例 B3 的完成。
案例二:天任务依赖小时任务
天任务依赖小时任务,需要等小时任务所有周期都完成才能开始调度。如果需要天任务尽量按照定时时间开始调度。则可以配置上游小时任务自依赖,待上游小时任务定时时间最近(且小于)的周期完成后,下游天任务就会被调度。
比如图中的连线关系是一个依赖关系,下游的十二点的天任务会根据就近原则就近依赖上游的八点钟,因为要按照小于它的时间去进行就近的依赖。
案例三:小时任务依赖天任务
小时任务依赖天任务且天任务存在跨周期依赖,则小时任务的所有周期都会依赖昨天的天任务。
比如实例 B1,B2,B3 按八个小时进行实例的生成,但是上游的实例 A 为一个天任务,而且存在跨周期的依赖,即15年1月1日的实例要去依赖14年12月31日的实例,等到14 年 1 2 月 31 日的实例都完成后,才能开始执行。
案例四:天任务依赖小时任务
依赖一层子节点:上游的小时任务跨周期依赖下游的定时天任务,效果即上游小时任务会在每一周期都会依赖上一版本的下游任务。
比如说15年1月1日上游的小时任务跨周期要依赖于上一周期即14年12月31日实例B的天任务,天任务完成后,小时任务才会开始运行。
案例五:小时任务依赖小时任务
下游节点设置依赖自定义节点(父节点 ID):
此 case 比较特别,即可看出其实这个依赖图中存在两个概念,既有跨周期(依赖上游小时任务的上一周期),又存在跨版本(依赖上游小时任务的上一版本的所有周期)。
比如图中实现为存在的依赖关系,虚线为自依赖。
调度依赖关系的具体实现示意图
调度依赖关系的具体实现:
调度的定时功能实际上是使用了 quartz 定时器,在每个任务完成的时候都会将所有下游任务查询出来。然后下游任务会返查是否所有上游都是完成了的。如果完成了,就会将下游任务注册到定时器中,所以可知在调度中存在越多的依赖关系,调度引擎的开销就越大。
比如上图左侧配置了上游三个节点,下游一个节点这种依赖关系,那我们会每天按照 23:30 统一进行节点开造,生成可以去运行的实例。运行规则为先运行上游第一个节点,再运行上游第二个节点,当三个节点都运行并返回成功,会开始判断下游节点是否到定时时间,到了运行,没到等待。如果在上游三个节点中某个节点运行失败,会导致下游节点一直处于等待状态中。
针对跨周期跨版本依赖的优化
和之前的依赖关系对比,可以看到有了自依赖后,跨周期依赖的边少了很多。这是因为如果有了自依赖,当前周期成功的前提必须是前一个周期成功了,于是下游跨周期并跨版本依赖就减少成了跨周期依赖。
天任务依赖小时任务(1)
【业务场景】
系统需求统计截止到每小时的业务数据增量,然后在最后一个小时的数据汇总完成后需要一个任务进行一整天的汇总。
【需求分析】
1)每个小时的增量,即每整点起任务统计上个小时时间段的数据量,需要配置一个每天每整点调度一次的任务,每天最后一个小时的数据是在第二天第一个实例进行统计。
2)最后的汇总任务为每天执行一次,且必须是在每天最后一个小时的数据统计完成之后才能执行,那么需要配置一个天任务,依赖小时任务的第一个实例。
天任务依赖小时任务(2)
【业务场景】
系统需求统计截止到每小时的业务数据增量,然后在最后一个小时的数据汇总完成后需要一个任务进行一整天的汇总。
【需求分析】
1)每个小时的增量,即每整点起任务统计上个小时时间段的数据量,需要配置一个每天每整点调度一次的任务,每天最后一个小时的数据是在第二天第一个实例进行统计。
2)最后的汇总任务为每天执行一次,且必须是在每天最后一个小时的数据统计完成之后才能执行,那么需要配置一个天任务,依赖小时任务的第一个实例。
小时任务依赖分钟任务(1)
【业务场景】
已经有任务每 30 分钟进行一次同步,将前 30 分钟的系统数据增量导入到MaxCompute,任务定时为每天的每个整点和整点 30 分运行,现在需要配置一个小时任务,每 6 个小时进行一次统计,即每天分别统计 0 点到 6 点之间、6 点到 12点之间、12 点到 18 点之间、18 点到明天 0 点整之间的数据。
小时任务依赖分钟任务(2)
【业务场景】
已经有任务每 30 分钟进行一次同步,将前 30 分钟的系统数据增量导入到MaxCompute,任务定时为每天的每个整点和整点 30 分运行,现在需要配置一个小时任务,每 6 个小时进行一次统计,即每天分别统计 0 点到 6 点之间、6 点到 12点之间、12 点 到 18 点之间、18 点到明天 0 点整之间的数据。