火山引擎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了解更多

相关推荐
Yz98765 分钟前
hive的存储格式
大数据·数据库·数据仓库·hive·hadoop·数据库开发
青云交5 分钟前
大数据新视界 -- 大数据大厂之 Hive 数据导入:多源数据集成的策略与实战(上)(3/ 30)
大数据·数据清洗·电商数据·数据整合·hive 数据导入·多源数据·影视娱乐数据
武子康8 分钟前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康10 分钟前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
苏-言17 分钟前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
Ljw...23 分钟前
索引(MySQL)
数据库·mysql·索引
时差95324 分钟前
Flink Standalone集群模式安装部署
大数据·分布式·flink·部署
锵锵锵锵~蒋27 分钟前
实时数据开发 | 怎么通俗理解Flink容错机制,提到的checkpoint、barrier、Savepoint、sink都是什么
大数据·数据仓库·flink·实时数据开发
二进制_博客28 分钟前
Flink学习连载文章4-flink中的各种转换操作
大数据·学习·flink
大数据编程之光31 分钟前
Flink入门介绍
大数据·flink