京东百万级调度系统(Buffalo)架构解密
一、调度系统简介
Buffalo调度是一款京东自主研发的分布式DAG作业调度系统。为京东的数据开发工程师、算法工程师、数据分析师等用户提供了离线作业的编排&调试、监控运维、DAG调度等系统能力,致力于打造行业领先的稳定高效、产品简洁高体验、任务监控全面、资源容器化、系统能力开放化的ETL调度系统。
在京东调度系统核心面临的挑战有以下几个:
二、核心技术方案
为支撑灵活的业务加工和工作流编排场景,快速的业务发展带来的任务量增长,以及保障整个系统的稳定性,我们从易用性、稳定性、以及高性能等方面做了很多的思考和优化,下面我将着重从这三个方面详细介绍。
1. 实体和编排调度模型
a) 双层实体模型
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-02-21-10-22kcli10rPsK7AxDyW.png)
采用主流的双层实体模型,双层实体模型中,包含两个核心概念:
相比单层实体模型,编排能力更强,有更好的灵活性,同时对于单个业务的整合打包和管理也更友好。
b) 基于实例的调度
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-02-21-14-31ATbea7SziriOATG.png)
任务定义是任务配置的载体,无状态,不可执行,任务当到达运行周期时,会产生相应周期的任务实例(产生实例的过程叫“实例化”),实例化时会根据任务的配置信息,包括:环节、上游依赖、数据依赖、运行周期等,生成当前周期实例,可理解为任务的一个快照,任务实例是真正可执行、并具有状态的对象。
基于实例的调度模式,其优点在于:
c) 分类分级调度能力
平台中的任务不通业务,重要性存在一定差异,为提升核心任务的保障能力,平台提供任务分类分级管理,和基于分级的调度能力,在客户端资源较为紧张时,会优先保障重要业务。同时任务等级信息会透传到底层集群,在底层计算集群层面也增加相应基于分类和等级的保障策略,保障核心业务的稳定性。
2. 高可用架构
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-02-21-15-55y0um21m21WD7gborX.png)
buffalo整体有分三层,每一层都具备高可用架构,使得整体具备高可用和容灾能力
3. 高性能
前面提到调度系统中随着任务量的增长,业务复杂度的提升,需要调度执行的DAG实例梳理,以及DAG的复杂度都会不断提升,buffalo主要从以下几个方面来做到高容量、低延迟的编排和调度。
1) 水平扩展
如上高可用架构部分介绍,调度引擎采用多活架构,可水平扩展,不同服务之间通过数据哈希分片,将任务负载分布到多台服务进行调度,同时各服务通过执行批次和状态进行幂等处理,保障任务执行的唯一性。
2) 事件驱动
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-02-26-20-41Coal8xtzgwKd2x41.png)
a. 定时轮询(如左图)
传统的任务执行方式大多采用定时轮询的方式,这种方式需要定时查询所有待执行的任务实例,然后逐一校验任务实例的依赖条件是否满足(如任务依赖、数据依赖、并发限制等),这种方式在面临大数据量任务时,有几个核心问题:
b. 基于事件驱动(如右图)
相比定时轮询,事件驱动不会采用定时拉取、全量校验的方式,而是在任务所依赖条件的状态发生变更时,才会基于事件做出相应的条件计算和校验动作,这样可以有效避免定时轮询面临的两个核心问题。同时针对不同的事件类型,可以分别进行异步并行处理,有效提升整体的处理性能。
3) 内存调度
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-02-27-09-033Sd33vYyLayAish.png)
前面提到Buffalo具备在物理机集群和k8s集群上启动任务执行的能力,所以需要具备这两种资源的管理和资源调度能力,资源调度的性能也是影响任务分发时效的关键部分。
调度引擎namenode采用的是多活的高可用架构,如果资源调度部分也采用该架构(如左图),那么涉及到同一资源的并发访问和修改的问题,进而引入分布式锁和外部存储,这样整体的性能很难达到理想的目标。
因此,我们在namenode多活架构的基础上,将资源调度部分做了一个主备架构的处理(如右图),会从多个namenode里选择一个作为主资源调度器,其他作为热备,所有namenode的任务资源请求都由主节点进行处理,这样主节点在内存中保存了所有的资源信息,资源调度过程在内存中就可进行,避免了分布式锁和对外部存储的依赖,性能有大幅提升。
4) 冷热数据分离
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-02-27-09-41UyN29qjJ27WqLaaGY.png)
当系统中任务量较大,任务执行产生的实例数据会快速增长,当前buffalo每日的实例数据增量接近百万,随着任务量的增长还会持续增长,如果没有适当的方案来处理,数据库很难支撑如此快速的数据增长。
调度系统中的任务有个明显特征 - 定时,就是任务会定时执行,执行完成后的实例,除人为干预外其状态不会再自动发生变更,这部分数据一般只会做查询,所以这部分数据可以做独立存储。我们将状态还会发生变更或频繁操作的数据称作热数据,将这些已经执行结束且基本只有查询需求的数据称作冷数据,并将冷数据单独存储。
当冷热数据分离后,有三个核心问题需要解决:
1)数据结转
任务实例执行完成,处于结束状态的实例都可以被结转,目前采用定时结转的策略。为避免冷数据单表数据量过大,结转规则可以按照季度、月或则更小周期进行拆分存储。
2) 数据定位
当数据结转到冷数据表后,这些实例的状态不会发生变更,单可能还会被未执行的实例所依赖,用户也可能会对这些实例做检索操作,所以这些实例需要能从冷数据表中快速被定位。
3)冷数据操作
冷数据被操作的几率比较低,但也存在操作的可能性,比如历史实例的重跑、强制成功等操作。为了保持调度引擎架构的简单性,所有相关的任务执行的处理,都是基于当前表(热表),所以为了能保障被结转的冷数据和热数据一样支持所有操作,冷数据被操作时会从冷数据表恢复至热数据表,从而实现与热数据相同的效果。
4、开放能力
开放API:通过Http协议进行开放,支持任务配置管理、任务实例操作、状态查询、日志查询等能力,通过藏经阁进行开放来服务业务
开放事件:基于JDQ异步消息的方式将任务状态、实例状态进行开放,联动业务个性化处理。状态发生变更及时同步,确保业务触达的及时性
三、未来规划
Buffalo调度系统仍在持续的优化和迭代升级,不仅提供更好的用户体验、更极致的性能,也包括容器化能力、插件化扩展能力、开放能力、精细化的资源管理能力等,希望大家提出更好的想法和建议,一起打造稳定、高效、易用的调度平台。