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

相关推荐
奥顺互联V几秒前
一次性部署:使用Docker部署PHP应用
大数据·mysql·开源·php
向阳12183 分钟前
mybatis 动态 SQL
数据库·sql·mybatis
胡图蛋.5 分钟前
什么是事务
数据库
小黄人软件7 分钟前
20241220流水的日报 mysql的between可以用于字符串 sql 所有老日期的,保留最新日期
数据库·sql·mysql
张声录112 分钟前
【ETCD】【实操篇(三)】【ETCDCTL】如何向集群中写入数据
数据库·chrome·etcd
无为之士18 分钟前
Linux自动备份Mysql数据库
linux·数据库·mysql
重生之绝世牛码19 分钟前
Java设计模式 —— 【结构型模式】外观模式详解
java·大数据·开发语言·设计模式·设计原则·外观模式
小汤猿人类32 分钟前
open Feign 连接池(性能提升)
数据库
喝醉酒的小白37 分钟前
Elasticsearch相关知识@1
大数据·elasticsearch·搜索引擎
边缘计算社区38 分钟前
首个!艾灵参编的工业边缘计算国家标准正式发布
大数据·人工智能·边缘计算