当前位置: 首页 > news >正文

面试官:怎样设计一个分布式任务调度平台?

大家好,我是君哥。

在工作中,批量任务调度的需求经常会遇到,比如下面的几个场景:

  1. 数据迁移:从数据库 A 批量读取数据,加工后把数据写入数据库 B;

  2. 消息通知:运营商批量给客户发送短信;

  3. 批量扣款:在还款日,银行批量扣除贷款客户的当期还款金额;

  4. 账务加工:系统通过日终跑批的方式加工当天的账务数据。

从开源框架来看,优秀的分布式任务调度框架并不少,比如 Quartz、Spring Batch、xxl-job、PowerJob 等。如果公司不使用开源框架,要自研一套,该如何设计呢?

今天就来聊一聊怎样设计一套分布式任务调度平台。

1.触发器

既然是任务调度,那触发器肯定是必不可少的。触发器就是控制任务什么时间开始执行,使用者可以定义好 Cron 表达式,到时间保证任务被触发。

除了定时触发外,也要设计通用的触发接口,方便地给外部系统提供触发入口。

在一些对账类的场景,可能多个系统联合对账,上游系统加工好后把账务文件送过来,触发本系统的批量任务进行对账。本系统对账完成后,要把对账结果异步通知给调用方。

2.调度器

调度器的主要作用是给待执行任务找到一台合适的机器,然后把它调度到这台集群上的待执行队列。

2.1 调度策略

调度器的调度策略可以有几种:

  • 调度到固定一台机器;

  • 以轮询方式调度到下一台机器;

  • 根据集群中各机器的资源状况调度到一台空闲的机器,这个比较难一些;

  • 随机选择一台机器;

  • 所有机器都执行。

在集群环境下,调度器对定时任务的作用是非常重要的,调度不好,很容易导致任务在不同机器上重复执行。

同时,调度器可以根据机器的资源情况进行任务调度,提高任务执行效率。

当然,也可能会有广播的场景,这时调度器需要把任务调度到所有的机器上执行。

还需要考虑的一个点就是任务优先级,优先级高的任务需要优先调度。

3 执行器

调度器把任务调度到某一个机器上后,就把任务交给了执行器。执行器可以定义一个线程池,接到任务后把任务丢到线程池中,等待被线程池调度。

执行器可以提供一个基类,任务类通过继承这个基类被调度平台识别。

4.任务链

任务链也是非常重要的概念,在任务调度平台上要支持任务链的定义,比如 task1->task2->task3 这样一条任务链,task1 执行完成后触发 task2,task2 执行完成后触发 task3。

任务链使用的业务场景很多。比如一个复杂度高、耗时很长的任务,可以拆分成多个子任务,这样如果有一个任务失败了,把异常问题解决后,从失败任务节点重新调起就可以。

实现任务链的方法有多种,这里提供两个思路供参考,一个是不定义任务链,给每个任务定义一个子任务,触发时只触发第一个任务,任务执行完成后执行子任务;第二个方法是定义一个任务链,任务链明确任务依赖关系。

5.熔断

批量任务一般用于处理数据量大的任务,比如给 10 万个客户发送短信通知。这会对本系统资源消耗较大,也可能会对下游系统造成压力。

如果没有任何防控手段,很可能会因为下游系统接口响应慢造成系统连锁反应。有了熔断能力,系统就可以及时发现问题并做出反应,对本系统和下游系统进行保护。

6.异常处理

异常处理的手段也是必要的。异常处理可以包含下面功能:

  • 用户可以方便地查看异常;

  • 解决异常后,可以方便地重新发起任务;

  • 遇到一些任务因为异常原因耗时太长,可以中断任务;

  • 遇到任务执行时间长,长时间占用系统资源,可以把任务挂起,给其他任务执行时间,其他任务执行完后可以再恢复这个任务。

7.阻塞控制

对于单机执行的任务,遇到任务排队的情况很正常。可以设置阻塞策略,比如按照 FIFO 方式进行排队执行,或者不做排队,有正在执行的任务时直接丢弃。

8.服务注册/发现

前面说到调度器会把任务调度到其中一台机器执行,那为了方便地管理集群中的机器,服务注册和发现功能也是很必要的。

9.任务监控

好多跑批任务是在日终执行,比如凌晨。把任务加入公司的监控体系,如果任务失败,触发监控告警,可以让运维人员和研发人员第一时间感知到。

10.控制台

有了上面的讨论,控制台的作用就很重要的。可以包括:

  • 触发器配置;

  • 触发类型配置;

  • 调度器配置;

  • 执行器配置;

  • 任务和子任务配置;

  • 异常处理;

  • 阻塞控制策略配置;

  • 任务执行状态查询;

  • 集群管理。

11.总结

通过本文的讨论,我们设计一个任务调度平台,需要下面的功能,希望对你设计和理解任务调度平台有所帮助。

图片

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【开源分享】PHP在线提交工单源码|工单管理系统源码 (附源码搭建教程)
  • STM32——外部中断(EXTI)
  • 【云原生】Job一次性任务详解
  • xss漏洞(二,xss靶场搭建以及简单利用)
  • 关于使用webflux开发思考
  • Animate软件基本概念:遮罩层和引导层
  • 【Python】解决Yolov8训练时,“OSError: [WinError 1455] 页面文件太小,无法完成操作”错误
  • [自学记录09*]关于模糊效果降采样优化性能的小实验
  • 【异常】npm install 出错几种解决方案
  • Git 的基本概念和使用方式。
  • 期权价格的奥秘:深入理解影响因素
  • C++入门基础知识(笔记):静态成员函数,所有对象共享同一个函数静态成员函数只能访问成员变量,类外访问不到私有静态成员函数
  • 河南萌新(2024)(河南农业大学)(旅途的终点)
  • 爬虫入门--了解相关工具
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • C学习-枚举(九)
  • DataBase in Android
  • Java 最常见的 200+ 面试题:面试必备
  • JavaScript/HTML5图表开发工具JavaScript Charts v3.19.6发布【附下载】
  • NSTimer学习笔记
  • React Transition Group -- Transition 组件
  • react-native 安卓真机环境搭建
  • Sass 快速入门教程
  • SpriteKit 技巧之添加背景图片
  • tensorflow学习笔记3——MNIST应用篇
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 阿里云前端周刊 - 第 26 期
  • 创建一个Struts2项目maven 方式
  • 分享几个不错的工具
  • 基于axios的vue插件,让http请求更简单
  • 将回调地狱按在地上摩擦的Promise
  • 两列自适应布局方案整理
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 前端面试之CSS3新特性
  • 如何在GitHub上创建个人博客
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 用 Swift 编写面向协议的视图
  • 原生 js 实现移动端 Touch 滑动反弹
  • ​​​​​​​​​​​​​​Γ函数
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • ######## golang各章节终篇索引 ########
  • #《AI中文版》V3 第 1 章 概述
  • #QT(TCP网络编程-服务端)
  • (AngularJS)Angular 控制器之间通信初探
  • (javaweb)Http协议
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • ***通过什么方式***网吧
  • .gitignore
  • .Net 6.0--通用帮助类--FileHelper
  • .Net Memory Profiler的使用举例
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .Net各种迷惑命名解释
  • .php结尾的域名,【php】php正则截取url中域名后的内容