任务调度架构设计

设计目标

  • 高频率调度
  • 高性能/高并发
  • 高可用

基于以上核心需求,以下框架:

Airflow:支持DAG(有向无环图),有监控界面集成,使用Python编写DAG,缺点在于官方无法解决单点故障,无法进行分钟粒度以下的高频调度
QuartZ:支持CornExpression,广泛用于Java调度,缺点在于耦合在Java上,高频调度难度高
Elastic-Job:国产框架,基于Zookeeper的实现。缺点在于耦合在Java上,高频调度难度高
Opencorn:国产,界面华丽
Unicode-Schdule:国产,耦合在Java上

任务调度的主要核心点在于是否为消息机制,以及是否高性能(内存性分布式)。

首先是Broker的设计,Broker负责与任务的发布方和任务调度方进行协调,必须保持高性能、高可用、原子性以及消息机制的任务发布,可选为Zookeeper和Redis。
必须支持DAG,也就是任务依赖
任务触发操作与Broker轻度解耦,独立出来做触发操作(Operator
多线程任务触发(Actor)

技术选型:Zookeeper、Akka(Scheduler、Actor、Http)、Celery(RabittMQ、Redis)

首先设计的核心在于Broker,其中包含消息、DAG和交互。
我们需要在Zookeeper中实现图(Zookeeper是树形结构):

红色存储的是图的因子,可以是一个任务,也可以是一个DAG(复杂的任务依赖)。每个因子存储自己执行的历史版本。
黑色存储图之间的关系,采用键值方式来表述以下图关系:

不存在的关系,ZK中不进行存储,这个设计尚未完成,对于任务的被依赖项完成后的消息检查需要进一步设计。
我们先cute一下流程:

今天累了,明天再写。
继续,为了方便客户端更新后触发上级任务执行的搜索,更新一下Broker的元数据设计,增加了反向索引

简单做一下名词总结:

  • Broker解耦客户端和任务调度的中间件,负责解决原子性、一致性、分布式等支持

  • Scheduler基于定时器和消息触发任务状态变化消息

  • Actor消息接收器,接收Scheduler消息,并传递给下一个消息环节

  • Operator负责接收Actor消息,进行任务执行的调度和操作,也有缓冲的作用。要求高性能、并发、自定义操作类型

  • DAG有向无环图,是一个虚拟节点,不包含任何任务。可以理解为一系列任务的根节点

  • Tash任务,需要具体执行的任务

  • Index根据DAG图,以键值存储,构建图存储的索引,自顶向下

  • Rindex根据DAG图,以键值存储,构建图存储的索引,自底向上用于通知

  • 元数据描述数据的特性,用于存储DAG的关系描述

DAG/任务的存储是一个扁平的结构,DAG与Task分散并行,每个Dag或Task的Children包含历史发布的任务并包含执行的状态,允许Client进行订阅。顶层DAG或Task总是指向历史中最新的History。

验证一下执行场景: