浅谈大数据任务调度平台

谈到大数据,避免不了hadoop, hive, spark 这些基础套件,但是在整个大数据开发的时候,我们面对的基本上都是数据开发平台和任务调度系统。数据开发平台一般直接面对业务同学,很大程度上影响业务同学的开发效率和节奏。而任务调度系统像一个黑盒一样,使用方一般都是数据开发的同学。但是任务调度系统在整个大数据体系中却占据着核心的地位。本人刚好负责一家互联网上市公司的调度平台,前段时间经历了一次大数据整体业务上云的过程,对调度系统有了更进一步的认识,本文将通过几个方面介绍以下调度平台整体结构和在工作中的使用经验。

关键字解读

kpi任务

在大数据任务调度中,有一些任务是每天必须在规定时间内完成的,这些任务一般拥有最高优先级,最大的资源使用占比,预警高优先级等。比如数据平台规定kpi任务必须要在早上9点之前产出,否则就是故障。

DAG

有向无环图指的是一个无回路的有向图。DAG调度即为工作流调度,是指任务从根节点依次往下执行,上游节点没有执行成功,下游不会执行,是一个自上而下的过程。

灰度发布

是一种平滑过渡的发布方式,AB test是一种灰度发布的方式,让一部分用户继续用A,一部分用户开始用B。如果用户对B没有反对意见。那么逐步扩大范围,将所有用户都迁移到B上来。灰度发布更多强调的是单一的新功能或者改进的逐步放量直到全量应用的过程。

最大最小公平算法

资源按照需求递增的顺序进行分配 ,不存在用户得到的资源超过自己的需求,未得到满足的用户等价的分享资源

Job

即任务,Job是调度系统中最小的单位。

Task

即任务实例,每次真正执行的任务。指的是某次具体的执行。

调度时间

上游任务开始调度,意味着任何一个依赖任务开始触发。
调度时间= 依赖任务触发时间的最小值

触发时间

上游任务结束调度,意味着所有上游依赖都触发了,满足调度的依赖条件。

数据时间

业务数据的真实时间。数据时间=(调度时间-偏移时间)。 在创建任务的时候可以填数据偏移,比如一个任务每天01:00运行,实际要处理的是上一天的数据,就需要根据调度时间-便宜时间。

目录

  • 什么是调度平台
  • 调度平台能解决哪些问题
  • 调度平台的整体架构
    - 数据平台的整体架构
    - 调度平台的架构设计
  • 系统升级的历程
  • 调度平台的核心功能点
    - 整体说明
    - 流程分析
    - 状态机
    - 队列
    - 多任务的周期触发
    - 并发数
    - 灰度
    - 状态恢复
  • 对比开源调度平台
  • 一些想法

什么是调度平台

首先举个例子,一般我们提交一个hive-sql, 首先需要登录服务器,连接上beeline,把sql脚本导入执行,获取日志和结果集,这没有什么问题。但是当大量的hive-sql需要执行的时候,并且sql之间有一定的依赖关系,或者sql需要定时在上午9点执行。这个时候手工执行任务就会明显效率低下。
调度系统的出现,让我们不需要关注任务具体是怎么提交,怎么调度,怎么执行,资源分配是否合理,依赖是否满足等。业务方把更多的精力放到业务上去,而不用去关心数据什么时候产出,数据质量的问题等。
那么什么是调度平台? 调度平台是包括调度系统,执行系统,通讯系统,日志系统,管理平台,专家监测系统,服务接口等一系列系统组合。

浅谈大数据任务调度平台_第1张图片

  • 从数据的时效性区分,调度分为离线调度和实时调度,一般实时调度都依赖flink+(k8s/yarn)去做,一般以流的形式或者微批。离线调度包括离线任务(hive,spark)和准实时任务调度(10mins一次批任务)。
  • 从处理类型上来区分,调度系统分为资源型和作业型。很多时候大家容易混为一谈,资源调度系统主要关注点是底层物理资源的分配管理,目标是最大化地利用集群机器的CPU、磁盘、网络等,比如yarn, k8s。作业调度系统关注点是在正确的时间点启动正确的作业,确保作业按照正常的依赖关系及时准确地执行。
  • 从以上两个方面,我们可以知道,在大数据的体系下,调度平台是离线和实时调度相互混合,资源型和作业型调度相互工作,来保证整个大数据平台的正常运行。而我们今天所要说的调度平台主要是任务调度平台和资源调度平台的整合,主要以离线/准实时数据调度平台为主。

很多时候我们会把具体的执行器纳入到调度平台的范畴,hive,spark,这些具体的执行器都是调度平台涵盖的东西。但是仔细想下,无论是大数据组件,其他只要符合DAG调度,时间调度的其实都可以使用调度平台来调度。一个真正强大的调度平台应该是开放的。有公共的执行器模板,业务方可以根据模板接入。调度平台只负责具体的调度和资源分配即可。调度和执行是两个阶段。

调度平台能解决哪些问题

解决业务方开发效率

  • 调度系统封装了整个任务的执行,参数建议优化,进度预测/查看,结果产出。业务方只需要提交脚本即可。开发效率大大提升。

  • 封装了大部分的任务类型python, shell, java, hadoop, hive, spark)的提交,业务方不用单独开发调度,一套系统满足大多数业务场景。

  • 任务参数自动化推荐,资源的动态分配和均衡利用,错误日志智能分析原因。

解决资源的合理分配

通过对整个任务生命周期的监控,集群资源的监控,通过动态分配调度队列,调整任务执行并发度,动态优化调度时间。在正常完成任务调度的同时做到资源的合理利用。

调度平台的整体架构

数据平台的整体架构

首先要看一下整个数据平台的架构:

  • 数据采集层 数据的来源一般是打点,数据库,以及业务系统等。
  • 数据存储层 数据采集层的数据通过数据交换,消息中间件流入到数据存储层。
  • 调度/资源管理层 业务方通过调度系统,进行数据ETL,分层,聚合。里面包括实时和离线调度。实时和离线的调度任务运行在资源管理里面。资源管理层负责任务的运行和资源的具体分配。
  • 数据加工层 包含了离线和实时的一些技术组件。
  • 平台服务层 数据平台的资产管理和运维。
  • 数据应用 通过统一数据服务接口调用底层的数据分发给数据应用。

从下图可以看出来调度平台是在底层与上游的中间层,所有的底层数据需要通过调度系统调用平台服务,离线平台和实时平台的组件进行加工生产,最终产出到下游应用或者回流到底层数据中。所以调度平台就类似一个大脑的地位,支配这上游和下游的应用的运行。
浅谈大数据任务调度平台_第2张图片

调度平台的架构设计

浅谈大数据任务调度平台_第3张图片
整个系统分为使用master/slave的方式进行部署,sever负责整体系统的元数据和调度,worker服务任务的具体执行。rest负责整个系统的通讯,logagent负责worker日志的上报和存储。spiderx负责整个系统的监控,报警,优化等智能诊断。
底层的通讯方式以akka为主,包括sever,worker,rest, logagent之间的心跳和传输。

系统升级的历程

1.0版本

支持最简单的工作流DAG调度,支持hive,spark的离线任务调度。任务的失败重试,历史数据的回刷任务,基本的页面查看功能。
遇到的问题:

  • 支持的任务调度类型比较少,仅支持最简单的hive,spark任务的调度,大部分是天级别的人,对于分钟级别的任务和复杂的依赖支持偏少。
  • 对于时间和DAG依赖相结合的任务无法友好的支持。
  • 系统的功能比较简单。在最上游的时候系统资源消耗比较少,但是到了下游,无法控制系统的并发度和资源的消耗。

2.0版本

  • 支持时间调度,时间DAG调度。
  • 任务的暂停,失败智能分析,历史数据回刷下游。
  • 执行队列的划分,kpi任务的生成
  • 灰度机器
  • 并发度的控制。
  • 调度系统的智能化分析。
    遇到的一些问题:
  • server端启动时间都在半个小时以上,遇到server挂机,大量的任务都被夯死。
  • worker机器手工部署比较麻烦,并且机器全部都是物理机,代码比较杂乱,版本众多,所有的任务脚本在每台机器上都有一份。发布繁琐。出现问题的概率很大。
  • 服务器全部是物理机部署,一般凌晨机器的利用率比较高。其他时间的利用率偏少。资源不能做到合理化利用。

3.0版本

  • 服务端加载资源优化。
  • 云原生容器化部署,容器资源弹性扩容。
  • worker端组件拆分,容器化部署。
  • task任务容器化拆分部署。
  • worker无状态改造,自动上下线。

产生的效果:

  • 整个平台从原来的混合部署,到分模块进行拆分,单独部署,每个模块都可以做到动态扩容。可以在资源空闲的时候,让出资源给其他系统使用。
  • worker发布轻量化,任务资源隔离。任务之间多租户。

调度平台的核心功能点

浅谈大数据任务调度平台_第4张图片
整个调度系统分为这几块:

  • 调度器
  • 任务分发
  • 执行策略
  • 执行器
  • 依赖管理
  • 状态恢复
  • 日志收集
  • 通讯
  • 周边的业务
  • 各种辅助监控,报警,以及优化任务。

调度器

调度器作为调度系统的心脏,主要作用是进行任务的调度。在该系统设计中,能实现对纯时间任务,依赖任务,时间+依赖任务的调度。
调度器由三个子模块组成:TimeScheuler, DAGScheduler和TaskScheduler, FairScheduler. 前两个主要时间调度和DAG调度,TaskScheduler针对具体的task判断是否符合依赖并且发送给下游的资源调度器FairScheduler。

四个调度器协同工作,共同完成对各种任务的调度,当完成对一个job的调度之后,提交一个task给Dispatcher。

调度器(Scheduler)和分发器(Dispatcher)之间是生产者和消费者的关系,Scheduler提交task给Dispatcher。只要Dispatcher空闲,就会拿走进行分发。

浅谈大数据任务调度平台_第5张图片

调度过程

浅谈大数据任务调度平台_第6张图片

  • TimeScheduler是对纯时间任务进行调度,内部维护了一个定时器每隔1s扫描是否有任务调度时间已经到达,对于纯时间的调度,当添加一个任务的时候自定计算下一次的时间,当时间到达的时候,提交给TaskScheduler
  • DAGScheduler对依赖任务记性调度,内部维护了一个JobGraph维护这job间的依赖关系,当有task状态反馈,TaskSchduler会进行状态处理,并且触发DAGChduler进行回叙任务的调度。对DAGScheduler的任意一次依赖触发,都会进行依赖检查,如果通过依赖检查,根据不同的job类型进行后续操作,如果是依赖任务调度,直接提交给TaskScheduler, 如果是时间调度,提交给TimeScheduler执行。
  • TaskScheduler对task进行调度,接收task的状态反馈,进行持久化,失败重试,后续任务触发等逻辑。TaskScheduler内部还维护了一个TaskGraph进行task的依赖触发,不会干扰DAGScheduler的正常调度。
  • FairScheduler是一个资源调度器,内部维护了一个动态的队列和并发度限流器,接收已经处于ready的Task任务,分发到对应的队列中,根据队列的资源分配决定任务的执行优先级。
  • TaskDispatcher通过push的方式,由资源调度器按照可扩展的分发策略,主动推送任务给某一个worker执行。内部有灰度策略,可以分发给对应的机器。分发机器的策略根据机器的资源,做了一定的负载均衡。
作业的生命周期
状态 描述
WAITING 任务依赖不满足或者任务调度时间未到。
READY Task实例满足了作业依赖
PAUSE 在Task处于WAITING或者READY状态下被手工暂停,只有这两种状态才能被暂停
ACCEPTED Task已经提交给Worker,并且通过了接收策略(资源够用)
RUNNING Task正在执行
REJECTED Task已经提交给Worker,但是没有通过接收策略
KILLED Task在运行的时候被Kill
FAILED 运行过程中出现错误,比如业务,系统错误
SUCCESS Task正常结束

ready包含4个子阶段:ready.queue(队列中) ready.dispatching(分发中) ready.accepted(接受) ready.Rejected(拒绝)。

当任务生成执行计划的时候,任务初始状态为WAITING。当任务进入执行队列时,状态更新为READY。当任务被work接收时,状态更新为ACCEPTED,反之更新为REJECTED。当worker开始运行任务的时候,状态更新为RUNNING。当任务运行成功后,状态更新为SUCCESS,反之更新为FAILED。
浅谈大数据任务调度平台_第7张图片
浅谈大数据任务调度平台_第8张图片

队列

队列主要负责调度系统资源的管理和任务优先级的管理。这个借鉴了yarn队列资源管理模式,并且根据队列的权值设置队列执行的优先级。队列根据任务类型,优先级和容量规划了5中不同类型的队列,任务在创建的开始就已经确定了自己所属的队列。kpi队列是优先级最高的队列,kpi任务享受最高级的优先级和最充足的资源。

队列名称 优先级 说明 权重
kpi队列 最高 一般用于kpi任务,在yarn上执行 最高
低延迟队列 一般用于临时任务,一次性任务
高优先级队列 中等 中等
普通优先级队列
重刷任务队列 最低 最低

在资源分配中队列的分配和队列的优先级是两个需要重点考虑的:

队列资源分配

队列资源分配包括初始化分配和队列的动态分配。
初始化分配包括队列的初始最小份额,最大份额,队列的权重划分。一般的做法是根据最大的资源分配数,单个队列最小份额,最大份额,和权重,计算每个队列可分配的资源数。

队列优先级
  • 当前执行数+等待数 < 最大最小公平分片数,并且权重高的优先调度。如果执行数都小于最小分片数,谁的队列空闲越多,谁优先调度。
  • 根据最小份额,当前使用量,当前buffer中的任务数,权重来划分优先级。
  • 当前使用量小于最小份额,优先调度,如果都小于根据空闲份额的比例优先调度。
  • 当前使用大于最小份额,根据单位权重使用量小的优先级调度。

对于hive,spark任务,如果是kpi任务执行,一般在yarn上划分出单独的队列去执行这些任务,目的是给这些任务留有充足的资源。
系统总资源,队列的权重是一个长期优化的过程,需要考虑当前使用的资源,需求资源和期望资源三个的占比然后进行优化。
在进行资源分配过程中,虽然最大-最小公平算法可以达到最大的公平,但是在实际的场景中,如果优先级较低的任务有资源的需求,虽然对应的队列已经达到期望的资源,但是在实际中我们还是会把其他的资源分配给这个任务,以达到资源的最大化利用,而不会去做抢占,因为抢占的本质在于快速四百,快速恢复。我们在处理这种抢占的时候,更多的是人工去kill任务。达到释放资源的目的。

依赖

依赖管理是整个DAG调度的核心。
调度依赖包括依赖策略和依赖区间

依赖分为任务依赖和作业依赖,任务依赖是DAG任务本身的依赖关系,作业依赖是根据任务依赖每天的作业产生的。两者在数据存储模型上有所不同。作业依赖树存储的多了两个时间:调度时间,数据时间。
job依赖:
浅谈大数据任务调度平台_第9张图片
任务依赖:
浅谈大数据任务调度平台_第10张图片

依赖是由依赖策略和调度依赖区间组成

依赖策略
  • 当依赖job在调度区间内有多个Task时候,需要指定依赖策略
  • | 依赖策略 | 描述 |
    |–|--|
    | All(*) | 调度区间内,所有依赖均成功 |
    | Any(+) | 调度区间内,任何一个依赖任务成功 |
    | First(N) | 调度区间内,前面N个依赖成功 |
    | Last(N) | 调度区间内,后面N个依赖成功 |
    | Continuous(N) | 调度区间内, 连续N个依赖成功 |
调度依赖区间

定义调度依赖的区间,通过基准时间与偏移时间来计算。
表达式 = (基准时间t, 起始偏移时间x(m), 结束偏移时间x(n))
比如 (“yyyy-MM-dd HH:00:00”, x(n), x(m))
基准时间t : 基准时间的格式化,默认"yyyy-MM-dd HH:mm:ss"
起始偏移时间x(n) : 基准时间"向前偏移x(n)时间,作为偏移时间的起始点。(正数向前,负数向后)
结束偏移时间x(m) : 偏移开始时间 向前偏移x(m)时间,作为偏移时间的结束点。(正数向前,负数向后)
时间单位 : 年 y 月M 周w 天d 时h 分m

浅谈大数据任务调度平台_第11张图片

灰度策略

目前灰度主要应用于需求变化比较强烈的worker机器上。主要是做一些任务执行模型功能性的修改或者新增。灰度机器和普通的机器不一样,是单独运行的。灰度机器只能执行灰度任务不能执行普通任务。一般来说灰度都是靠灰度策略配置的。灰度策略的条件决定了灰度操作的多样性。

灰度策略属性
  • 灰度比例
  • 时间范围
  • 责任人
  • 报警机器
灰度策略条件
  • 任务维度
  • 业务域维度(部门,业务线)
  • 任务类型(单次,周期)
  • 责任人

一般我们会用在修改bug的场景,比如某个脚本有问题,需要进行debug操作,我们会开一个单独的机器作为灰度机器,避免对线上数据做成影响。对于修改的脚本我们会在灰度机器上面跑稳定之后再同步分发到其他机器上面去。

表达式

一般有三种表达式类型:

  • cron 表达式,可以设置小时,分钟,日,周,月等。
  • Fixed Rate固定时间间隔(比如40min/次,这个很难用cron表达式) 固定频率一般分钟级别。
  • Fixed Delay 每次执行完成之后,延迟时间再次触发。一般用于秒级任务。
任务类型

通过上面的表达式我们可以得到任务的类型:

任务类型 cron Fixed Rate Fixed Delay 纯依赖任务
cron 1 1
Fixed Rate 1 1
Fixed Delay 1 1
纯依赖任务 1

如果强调任务间隔,建议用后两者,如果强调任务在固定时间执行可以用cron,cron有时可以替代Fixed Rate。
大部分的场景下我们用纯依赖和cron依赖比较多,一般都是分钟级任务或者是天级任务,它们有个共同点是最上游必须是时间或者时间依赖任务。但是在算法侧有一些纯依赖的应用,就是root节点也是纯依赖没有时间的,这个时候就需要通过api或者手动调用触发root节点执行。

作业计划

先说一下什么是作业计划,比如调度系统有1w+的job。这些job有每天执行一次或者多次,有纯依赖,有复杂依赖。一个job从第一次创建,如何知道下一次的执行时间,依赖等。就需要通过创建作业计划来完成。
作业计划有两种创建模式:

  • 每天生成第二天的
  • 当前任务执行初期或者完成时自动自动生成下游plan。

如果调度系统简单,直接可以使用第二种,但是对于1w+job的系统,或者某个纯依赖的上游任务很多,或者上游也是纯依赖并且图深度>10. 显然第二种会影响执行的效率。我们采用的是第一种和第二种的结合。

执行计划的生成有多种方式:

  • 任务提交/修改时候,内存中生成下一次的执行计划,并且持久化全天的执行计划。
  • DAGScheduler在上游依赖满足时候,如果是时间调度,触发生成下一次的执行计划。
  • TimeScheduler 如果是时间调度,在调度当前任务的时候,自动生成下一次的任务。

在作业计划中,最重要的是计算下一次的执行时间。

  1. 临时任务直接使用当前时间
  2. 判断任务的调度时间表达式是否存在,如果存在就是时间/时间依赖调度,根据表达式的类型和当前的调度时间计算下一次的时间。(普通cron表达式,Fixed Delay, Fixed Rate),
  3. 如果不存在任务的调度时间表达式,就是纯依赖任务。轮询其上游依赖。
  4. 如果上游依赖为空直接返回
  5. 如果上游依赖表达式为空,说明没有依赖策略。只依赖当次上游任务成功。需要递归查找上游任务。
  6. 如果上游依赖表达式不为空,说明是有依赖策略,如要根据依赖策略,上一次调度到这次的调度依赖区间,计算下一次任务的执行。

任务恢复

任务恢复是整个调度系统中除了调度流程以外最复杂的功能。在系统某一组件出现问题,导致宕机。需要对机器进行重启或者启动备份机器,恢复成正常调度。
在系统宕机过程中,任何一个环节都会出现问题,server端,worker端,rest端等等。
比如server端出现问题,我们可以做HA, 用zk来选举master节点,如果一个节点宕机,其他节点自动重新初始化数据或者做数据同步。
在系统恢复的过程中,任务的自动恢复是比较复杂的,因为任务的状态在不同的流程下有不同状态。虽然任务的状态能同步持久化到数据库中,但是不同任务在不同的环节如何加载,恢复。其实是比较繁琐的。
以下图为例,一个任务从提交到最后执行成功的所经历的状态转变。在机器出现故障的时候,任何一个环节都有可能有问题。所以需要从任务状态的角度去看整个任务的恢复。
浅谈大数据任务调度平台_第12张图片
server端无状态保证:
有两种方案:

  1. server端的高可用。通过zk选举可用的master节点,并且server 端到端之间需要进行数据同步,server与worker, rest, logagent之间切换连接到最新。内存中的数据需要做分布式缓存。
  2. server端重启高可用,保证重启时间很短,重新刷新内存中的数据。目前我们使用的是这种方案:
    • 恢复运行时任务
    • server端,恢复plan
    • server端,恢复schedule(waiting, ready)任务
    • server端,恢复纯时间调度的下一次plan
    • server端, 恢复纯依赖任务

worker端无状态保证

  • 任务状态持久化到磁盘,worker宕机了之后,重启后根据任务获取yarn,k8s上的任务状态。轮询至完成状态后上报。
  • 任务状态上报有重试机制
  • worker端上下线自动化,server池子中任务发现worker不存在,根据woker的任务类型,自动为任务重新切换worker执行或者报警。

云原生改造

云原生改造的目的有三个

  • 充分利用资源,在系统繁忙时弹性扩充资源,在系统空闲时候把集群资源让给其他系统使用。
  • 降低worker的复杂度,最初worker是多台物理机,上面混合部署了数据交换,spark-history,beeline,dqc等应用。现在通过云原生的方式,把每个应用打成单独的镜像,一方面降低了worker的复杂度,另外一方面在容器中执行小任务,避免了多进程在资源不足时候的相互影响。
  • 任务执行隔离 把消耗资源较多的任务和消耗资源低的进行分离。在旧版本中worker的职责是负责任务的执行,日志/监控的上报等。耗资源多的任务和耗资源少的任务混合在worker上执行。在等待任务较多的情况下,这种情况不能提升worker的并发度。我们把耗资源多的任务(数据同步,spark通过rest与容器打通,把具体的执行放到容器当中,worker只负责日志的手机和监控的上报)。并发度会大大提升。

在整个系统迭代过程中,我们发现算法类应用一般在白天暂用集群资源比较多,和数据平台刚好形成一个互补。以云原生的方式进行部署应用,可以大大提升机器的使用效率,降低成本。
在最初的改造过程中,worker云原生时,设置弹性扩容最小内存为16G, 在凌晨dump任务并发数高的时候,会出现容器POT OOM. 解决方案有,worker增大内存,server投递减少并发数,任务jvm内存固定最大最小值,worker fork任务进程时候判断最大容量是否充足。在后面进一步改造的时候,为了把重量型任务和小任务隔开,通过任务云原生化,进一步资源隔离。

一些想法

  • 任务的生命周期管理,是一个挺麻烦的事情,对于一些短期的任务。需要设置合适的生命周期保证到截止日期之后下线该业务。对于kpi任务默认自动延长其生命周期。任务的owner离职之后,需要找到任务新的负责人,继续维护脚本。在这些场景下,如何保证任务高质量的运行,就需要强制限定一些规则,比如过期提醒策略,责任人离职变更策略,空闲任务监测,血缘关系中任务产出数据无访问记录检测等。

  • 监控报警,失败重试 任务的失败重试,一般都是分析失败原因,如果是系统问题,一般重试一次,如果再次失败就报警,如果是超时,网络,一般会根据重试策略进行重试,默认是3次,失败通知值班人,如果是业务问题,再联系任务owner, 尤其是关键链路上因为偶然因素导致的问题。失败重试,超时报警,一般都是通知值班人,而不是任务owner。这个在调度平台产品化时很重要。

  • sever的HA 目前还是很难完成,目前做到的只是通过zk来保证一个机器挂了之后,另外一台机器重新初始化。在我们的场景下,sever需要初始化大量的数据在内存中(整个dag都是存储到内存中的),整个初始化的过程在10~30mins左右。如何能保证状态机和内存数据与备份机器无缝衔接,这个就需要分布式缓存和图数据库来存储依赖关系的保证。而且目前sever端和其他服务端通过akka进行通信,在zk选择新的sever端的时候,akka的通信也要重新切换到新的server端,并且确保旧sever端的数据不影响新的sever的服务。这个是未来的一些考虑。

  • 提供更多插件化的任务接口, 支持更多不同形式的任务接入比如(go,spring等),并且与调度系统进行剥离,调度系统只负责任务的调用,而不在支持具体任务的执行逻辑。

  • 任务执行优化智能运维 主要是任务重试的优化,在我们的系统里面任务重试主要是指失败的任务,根据日志分析失败原因,并且匹配任务失败策略。如果匹配成功就根据策略进行重试,如果没有找到失败原因就通知业务方处理,虽然我们一直在完善整个链路的失败重试策略,但是对于一些莫名其妙的问题,尤其是关键链路上,凌晨值班的同学在接到电话报警的时候总是要处理,其实应该让这些没有匹配上的任务自动延时重试一次。将会大大降低值班的次数。并且这种做法针对于worker挂掉自动拉起的情况,也有一定的恢复功能。

  • 数据源同步进度优化 主要涉及一些kafka消息报,增量数据库同步进度收集,在一般的处理中进度收集和具体的执行是单独分开的任务,而且并没有关联的关系,这个在整个运维管理下都是比较麻烦的,针对这种任务,需要特殊处理进行任务的绑定已经延迟通知。

  • 动态调整资源的波峰/波谷 在以往的场景下,我们会用时间依赖调度比较多,好处就是可以根据时间调度来人为的调整任务的开始调度时间。根据yarn集群和k8s集群的资源使用趋势图,来手工的调整整个DAG图中任务的调度时间。一般的做法是把某个时间点资源占用比较多任务拉取出来,手动调整调度时间到资源比较低的点。以达到资源的合理利用。如果是能够根据资源占用动态调整DAG图任务的开始调度时间,这个就比较完美了。

  • 一些工作流调度的特殊场景 在实际的开发过程中,尤其是算法侧的对于调度平台有着不一样的需求(自定义工作流任务的编排,可以根据业务系统触发工作流任务的执行,而不用考虑周期调度),算法的业务注重的是任务的工作流编排和随时随地触发,这些任务可能执行一次或者多次。处于周期任务和临时任务的边界。所以是否需要页面化树节点的编排和动态触发工作流执行?这个需要想一下。

  • 资源的使用量优化

    • 资源的使用统计 资源的使用量主要是cpu和内存,在最初的版本上,任务主要在yarn上和worker主机上,yarn上面可以计算cpu的时间,申请cpu的个数,内存大小。worker主机上只能计算任务使用量,而且计算量比yarn偏小,而且口径基本上统一不了。所以在资源使用上主要以yarn为主。在现在的版本上,资源都在k8s和yarn上面,资源的统计口径就能保持一致。

    • 资源使用优化,从应用级别进行优化,对于spark任务可以根据申请的内存和cpu大小计算空闲cpu和jvm使用量。提醒业务进行资源优化。从整体链路上,根据最终输出数据的读取频次进行数据的优化,比如最终输出的数据1个月以上已经没有读取了,可以从链路的末端依次提醒对应的业务方下掉对应的业务,以达到资源的合理利用。

    • 任务资源弹性扩容,主要是针对大促场景下,不仅仅是平台集群进行扩容,对任务也需要扩容,尤其是一些核心的任务,内存,cpu需要成倍的扩容,目前我们都是通过人工来做,大概率会大促第二天任务产出延迟,如果提前进行自动化的任务扩容,任务的产出延迟就可能大大改善。

最后

感谢数据平台的前辈们,尤其是天火老师的思想,站在巨人的肩膀上看问题果然简单了很多。

参考链接

数据平台作业调度系统详解-理论篇
数据平台作业调度系统详解-实践篇
最大最小公平算法

你可能感兴趣的:(调度系统,大数据)