写点什么

火山引擎 DataLeap 背后的支持者 - 工作流编排调度系统 FlowX

  • 2023-10-26
    浙江
  • 本文字数:3502 字

    阅读完需:约 11 分钟

火山引擎DataLeap背后的支持者 - 工作流编排调度系统FlowX

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群

背景介绍

业务场景

在日常工作中,我们时不时需要对某些逻辑进行重复调度,这时我们就需要一个调度系统。根据不同的调度需求,可以广义分为两类:

定时调度

根据一定的周期对任务进行重复调度。这类比较容易实现,通常一个 crontab 就可以对任务进行定期调度。但是简单的 crontab 任务在实际生产中应用会有一些挑战,包括失败处理、监控以及部署、跨机器部署、重试等。

依赖调度

依赖调度类型,通常是指某个逻辑的触发需要在特定的“事件”发生之后,这个事件可以是上游某个任务完成,也可以是某个指定路径数据就绪,或者其他外部触发等。任务间的依赖会形成一个 Worflow,典型的一个简单 WorkFlow 如下图:

上图中,“计算用户留存率”需要等待“数据预处理”完成,那么“计算用户留存率”就对“数据预处理”任务产生了依赖。任务间的依赖可以有“业务时间偏移”需求,如“计算留存率”需要根据今天的数据与 7 天前的数据进行计算,那么这个节点需要同时依赖“数据预处理”当前业务日期的任务实例以及 7 天前的任务实例。只有当两个业务日期的实例都成功了,才会触发当天的“计算用户留存率”任务,避免产生脏数据。

业界选择

调度系统在业界已经有不少方案,初期也调研了相关的开源调度系统。主要包括以下几个

Airflow

Airflow 最早是由 Airbnb 开发然后贡献到 Apache 中的一个调度系统,目前使用较多,社区也比较活跃。用户可以通过 Python 定义工作流以及调度频率等。Airflow 定位是一个通用的调度系统,支持单节点以及多节点部署。整体架构图如下

其中调度的主要逻辑在 Scheduler 模块中,Scheduler 通过“轮询“的方式从数据库中拉取需要运行的任务交由 Worker 去运行。多节点模式下,Scheduler 是通过 Celery 进行任务分发给多个 Worker 中。需要说明的一点是,即使在多节点模式下,Scheduler 本身也是一个单点故障。

Azkaban/Oozie

Azkaban 和 Oozie 分别是由 LinkedIn 和 Apache 开源的调度系统,重点专注于 Hadoop Batch 的调度,更好的集成了 Hadoop 相关功能,方便用户可以简单跑起 Spark/Hive 等任务。其中与 Airflow 不同的是 Azkaban 和 Oozie 是通过配置/DSL 的形式来进行 DAG 的配置。在社区活跃度上与 Airflow 相比有一定的差距。

其他开源系统

其他开源的还有一些类似 DolphinScheduler 等,既然有了这么多开源的系统,我们为什么还决定自己造轮子 - FlowX?

  • 我们需要的调度系统定位是一个通用的的调度系统,能够处理多种节点类型;

  • 高可用,可伸缩。这个调度系统会承载着类似基础数仓等一些核心链路,需要保证调度的高可用。同时随着公司业务的不断发展,预期调度的任务数会快速上涨,需要能够水平扩容;

  • 易二次开发,公司的业务针对调度系统会有一些定制化需求,如支持自定义镜像、增加控制节点、增加超时自动重试等功能,需要可以低成本地对系统改造;

  • 易于集成,做为一个集中化的调度系统,计划与公司其他系统进行集成,如根据任务的依赖关系可以提供数据血缘功能,供数据地图工具使用;

调度能力介绍

Functional

  • 支持定期调度(分钟级、小时级、天级、每周或者每月的某几天)

  • 支持依赖执行 -- 任务间的依赖 -- 外部 HDFS/Hive partition 依赖 -- 任务自依赖(依赖前一个业务时间的实例) -- 支持不同周期的任务依赖,比如小时级别的任务可以依赖天级别的任务 -- 支持依赖业务时间偏移(如当前实例依赖 n 天前上游任务实例,或者历史某段时间的上游任务实例)

  • 支持暂停、取消运行中实例,失败自动重试和告警

  • 历史数据回补

  • 可以针对 Worflow 中指定节点以及全部下游进行重跑以修复如数据质量引起的问题

  • 任务并行量的控制

  • 依赖推荐 -- 系统会根据用户的 SQL 逻辑自动提取出所需依赖的上游表 -- 如果上游表是调度系统内的任务产出的,那么会推荐出上游任务 -- 如果上游表不是系统内的任务产出的,那么会推荐 Sensor 探针任务

Non-functional

  • 保证高可用、扩展性和故障恢复的准确性,不漏调度和不重复调度

  • 调度延迟秒级

  • UI 以及 API 多重配置方式

技术实现

基本概念

DAG

DAG 全称是 Directed Acyclic Graph(有向无环图)。调度系统里,一个 DAG 表示一组相关的任务,任务之间的依赖关系用一个有向边来表示。如下图所示,A 到 B 有一条边,代表 A 是 B 的前置任务,即任务 B 依赖任务 A 的运行。

如图所示的任务依赖关系,一种有效的执行顺序是 A -> G -> B -> D -> C -> E -> F。

任务

调度系统中 DAG 中的每个节点代表一个任务,代表着一段逻辑,用户可以在任务里面实现不同的业务逻辑。

实例

系统根据每个任务指定的业务日期会产生的一个实例,实例是调度的基本单位。同时任务之间的依赖关系最终都会转化为实例间的依赖关系。

系统架构图

模块解析

WebService

WebService 做为外部系统与用户交互的主要入口,用户通过 UI/API 创建任务等操作是通过 WebService 进行交互的。主要的功能如下:

  • 权限检查

  • 任务开发以及运维

  • 实例运维

  • 日志信息获取

  • 项目管理

Master

Master 是系统的“心脏”。目前 Master 的容灾是通过 ZK 进行主备的。Master 的主要功能包括任务依赖图的管理、调度优先级管理、Quota 管理、实例分发、Scheduler 和 Worker 的监控。

  • 任务依赖图管理

    维护任务间的依赖关系,并且提供 Service 给其他模块,如查询某个任务的上游以及下游等信息。

    生成计划/重跑实例,向 scheduler 发送 INSTANCE_CREATE 事件。同时 Master 会定期提前生成未来一段时间内需要运行的实例。

  • 调度优先级管理

    借鉴 yarn 的公平调度算法思路来解决高负载情况下调度顺序的问题。通过任务属性划分优先级队列,确保任务根据优先级有序调度,达到流控 &加权均衡的目的

  • Quota 管理

    通过多维度指标 + 正/反向匹配 + 时间区间限制来灵活匹配目标任务,限制对应的并发度,来达到“凌晨保证系统调度资源,白天保证回溯重跑数据资源”或者“限制 eval task 占用过多资源”等提高系统资源利用率的目的

  • 实例分发

    通过依赖检查并且到达计划时间的实例会由 master 进行分发

    根据不同的任务类型,Master 会决定交由 worker 去执行还是直接提交到 K8s 中

  • 模块监控

    维护当前活跃的 Scheduler 列表,创建的实例会交由对应的 Scheduler 去进行调度检查。

    维护当前活跃的 Worker 列表,将实例分发到对应的 Worker/k8s 去执行。

    监控 scheduler 以及 Worker 状态,在状态异常的时候主动将实例分发到其他节点上。

Scheduler

Scheduler 部分主要包含三个子模块

  • Dependency Checker

    从事件队列中获取 Master 分发过来的事件,检查相应实例的上游依赖。如果依赖都满足的话则会将事件丢入下一个队列中

    如果此时依赖还不满足,那么此次事件会被丢弃,当前实例会由上游的成功事件来主动进行触发,避免占用大量资源轮询上游状态

  • Time Checker

    从队列(DelayedQueue)中取出通过依赖检查且到达运行时间的事件(实例)。如果是普通任务类型交由 master 去分发执行,如果是 Sensor 探针类型的任务则会丢到 Sensor Processor 去检查外部数据的就绪情况

  • Sensor Processor

    目前实现了两种类型的 Sensor 检查,HDFS 路径以及 Hive table/partition。

    Sensor 会去检查对应的 HDFS/Hive 数据是否已经就绪,如果就绪,就走触发下游流程。如果未就绪,在 Sensor 的一次检测中不会进行不停轮询,而是借助了任务自动重试机制,等待指定的时间(目前是 5 分钟)之后会再次进行检查。直到外部数据 ready 或者超过重试次数。

Scheduler 同时会将自己注册到 ZK 里面。Master 是通过 Zk 进行感知哪些 Scheduler 是处于可用状态。Scheduler 重启的时候会从数据库中捞回本 Scheduler 处理中的任务进行恢复。

Worker

Worker 是具体负责任务执行的模块。通过依赖检查的实例会由 Master 分发到 Worker 中由 Worker 进行执行并且监控任务运行状态。Worker 中会启动子线程对任务进行提交以及监控,并且主动向 Master 汇报状态以及进行失败重试等操作。 Worker 同样会将自己注册到 ZK 里面以便 Master 进行感知。

Zookeeper

系统中用到的 ZK 主要是以下几个目的

  • 选主:Master 是由 ZK 进行选主的来实现主备,达到系统高可用目的。

  • 探活:Master 是通过 ZK 来感知 Scheduler 和 Worker 可用列表。

  • 服务发现: Scheduler 和 Worker 会通过 ZK 来发现 Master 的监听 ip 和 port。

未来规划

未来这个调度系统主要是会针对“功能增强”以及“易用性”进行完善。主要包括:

  • 提供更多交互方式,包括 CLI 以及配置文件等形式

  • 完善节点类型(如控制节点)

  • 接入更多系统,如公司的 Cronjob 以及 FaaS 平台

  • 轻量化部署

总结

当前自研的调度系统 FlowX 已经具备比较完善的功能,已通过火山引擎 DataLeap 对外提供服务,经过一年多的打磨,系统稳定性也已经有了保障。系统上已经承载了很多基础数据链路以及多方向业务应用。针对业务真正做到了“集数据产生、数据传输、数据处理、业务流程”于一体。交互方式上,除了以 Web UI 的操作方式接入,同时有一定的 API 接入能力。


点击跳转大数据研发治理套件 DataLeap了解更多

发布于: 刚刚阅读数: 4
用户头像

小助手微信号:Bytedance-data 2021-12-29 加入

字节跳动数据平台团队,赋能字节跳动各业务线,对内支持字节绝大多数业务线,对外发布了火山引擎品牌下的数据智能产品,服务行业企业客户。关注微信公众号:字节跳动数据平台(ID:byte-dataplatform)了解更多

评论

发布
暂无评论
火山引擎DataLeap背后的支持者 - 工作流编排调度系统FlowX_大数据_字节跳动数据平台_InfoQ写作社区