一个著名的任务调度系统是怎么设计的?

线上定时任务quartz造成线程数量暴增,导致-bash :fork : Cannot allocate memory 一、问题描述: 上篇文章写道在部署生产产生了OOM问题,对jvm参数优化后比之前好些,但是感觉线上得了一种慢性病,突然就出现内存不足的提示,如下: 从而导致应用不能使用,第一反应就是内存满了,第二反应就是代码出现了内存泄漏,毫无疑问一般都是第二种情况造成的,于是就观察了几天生产的内存使用情况,发现还有一半的内存没用,突然就又报那个错了。这个时候感觉有点不对劲,难道内存会突发性的使用完么?好机会无奈之下只能重启服务器,具体上线内存监控也没发现什么问题,有仔细看了下那个提示:-bash :f... 阅读详情

实习生张大胖

这是个代码写得很烂的电商系统,只要运行一段时间,服务器就会出现Out Of Memory。

别人都忙得四脚朝天,于是实习生张大胖被抓了壮丁去研究为什么会出现OOM。

刚入行的张大胖技术水平一般,“装模作样”地看代码,研究日志,请教老员工,一个星期过去了,还是一无所获。

周一例行的项目会议上, 大家似乎要看张大胖的笑话了,没想到他却提了一个歪招:“这个OOM问题非常复杂,一时半会儿也解决不了,要不我们定时重启服务器怎么样?”

一脸严肃的项目经理老梁点点头:“以目前的情况看,也只能如此了。但是不能让服务中断,这样吧,公司有两台服务器,一台在凌晨1点重启, 另外一台在凌晨2点重启。”

得到了领导的首肯,张大胖赶紧行动,周末他其实已经做了准备,研究了Linux上的crontab,它的格式是这样样子:

640?wx_fmt=png

每天凌晨一点重启系统,可以这么写:

0 1 * * *  restart.sh

(码农翻身注:这里只是个简单的例子, 实际上crontab及其灵活)

这个OOM的问题被张大胖灵机一动给解决了,或者说,被临时隐藏了。

crontab达人的烦恼

大家知道张大胖擅长crontab, 都把一些定时的任务扔给他去做: 什么定时统计报表,定时同步数据,定时删除表中的无效订单...... 等等。

张大胖整天面对的就是crontab和脚本,都快要吐了。

不仅如此,同事们还经常提出一些“变态”的需求:

“大胖,那个定时任务运行得怎么样了?”

“大胖,我想把那个定时任务给停掉。”

“大胖,那个定时任务今晚别运行啊!”

“......”

张大胖真是烦死了,他心想,要是提供个界面让大家使用就好了, 可是crontab似乎并不支持。

要不自己开发一个?

有一次张大胖偶然发现了JDK中的Timer类,似乎也是做这些定时任务的, 不由地眼前一亮,但是仔细研究以后就发现,JDK的Timer还是太简单了,做点简单的定时任务还行, 对于复杂的情况,尤其是复杂的时间策略,还是力不从心。

另起炉灶

看来自己需要从头设计了,张大胖想到了公众号码农翻身的一篇文章《一个著名的日志系统是怎么设计出来的?》, 小张用“正交”的原则设计出了Logger, Appender, Formatter这些类。

640?wx_fmt=png

我也可以使用同样的原则啊,小张能行,我凭什么不行?

说干就干,先想想需求,非常简单,不就是定时地执行任务嘛!

“任务”应该是正交中的一个“维度”,我可以抽象出一个接口叫做Task , 嗯,还是叫做Job吧。

对使用者来说,他需要提供一个实现类出来,在实现类中描述要做什么事情,比如:生成报表,复制数据......

640?wx_fmt=png

“定时”该怎么处理? 定时,定时触发,干脆叫做Trigger吧。

这个Trigger 可以指定什么时间开始,时间间隔,运行多少次, 能覆盖大部分需求了。

可是张大胖转念一想,如果有人要求类似日历的重复间隔该怎么处理? 比如每月的第一天运行,或者每周的最后一天运行,该怎么办?  crontab特别适合描述这种情况,对,可以搞一个类似于crontab的Trigger。

看来Trigger最好也是个接口,我来提供几个默认的实现,比如SimpleTrigger,CronTrigger,用户还可以扩展,这样就灵活了。

640?wx_fmt=png

Job和Trigger也是正交的关系, 两者可以互不影响,可以独立扩展,真是不错, 张大胖不仅得意起来,这设计也很简单嘛!

但是怎么把这两个家伙结合起来?

必须得有个“大管家”才行,这个大管家应该可以接受Job, 然后按照各种Trigger去运行,嗯,叫做调度器Scheduler应该不错。

张大胖画了个草图,来展示三者之间的关系:

640?wx_fmt=png

设计得差不多了,可以进入开发阶段了, 因为是自己要写一个类似于框架的东西,让别人去使用,张大胖开发起来非常有激情,即使是利用晚上和周末的时间来写代码,也是像打了鸡血一样,根本不觉得累。

一个月过去了,第一版新鲜出炉。

这个版本不仅有核心的API像Job, Trigger, Scheduler ,张大胖还专门开发了一个界面,用来展示定时任务的进展,例如什么时间运行,运行了几次,失败了几次......等等。

张大胖把它叫做“大胖定时任务调度系统”。

持久化

他兴奋地拿去让项目经理老梁看, 可是老梁并不感冒,面无表情地说:“你这个小软件有啥用啊。”

张大胖被泼了一盆冷水,依然热情满满地推销:“用了我的这个定时调度系统,任何人都可以轻松地启动,停止任务, 咱们项目中所有的定时任务一目了然。 大家就不用找我来手工调整了。”

老梁开玩笑地说:“奥,那你的实习工作就可以结束了,哈哈。”

正巧CTO Bill经过,他饶有兴趣地看了一会,提了一个问题:“假设你这个大胖调度系统在运行的时候,机器突然间Down掉了,怎么处理?”

张大胖一脸懵逼:“什么怎么处理,重启机器呗。”

Bill 说: “之前的任务还能接着运行吗,比如说一个任务需要运行100次,在机器down掉之前运行了90次,重启后能不能从第91次运行?”

张大胖有点发窘,不好意思地挠挠头:“这一点我还真没考虑到,我现在都是在内存中记录运行的情况,看来得做持久化了。”

Bill 听到持久化这个词,知道张大胖已经Get到了,他说,你把这个持久化实现了,到时候直接向我汇报。

得到了CTO的赏识,张大胖不敢怠慢,赶紧进行新的设计, 他抽象了一个叫做JobStore的接口,表示Job的存储,像什么Job,Trigger, Job运行情况都存储在其中。 

下面有两个实现,分别对应内存存储和数据库存储。

640?wx_fmt=png

虽然SQL是标准的,但是不同的数据库还是有细微的差异, 张大胖觉得得把这些差异给封装起来, 他又提取了一个接口叫做DriverDelegate, 屏蔽了数据库细节,让DbJobStore使用。

他还提供了一个缺省的实现StdJDBCDelegate,如果那些数据库还有独特的实现,那就写个子类就行了。

640?wx_fmt=png

高可用

“大胖定时任务调度系统 2.0” 开发完成以后,张大胖仔细地想了一遍,似乎没有什么漏洞了,决定正式向CTO Bill去汇报。

Bill 亲切地询问了张大胖加班加点设计和开发的情况,对他这种不计较个人得失,一心一意为公司谋福利的精神表示了高度的赞赏。

张大胖受宠若惊。

Bill话锋一转:“我们的系统最近用户越来越多,老板特别提出了高可用的需求,系统的各个组件也得达到高可用!”

“高可用? 拿我的定时调度系统来说,就是说可以部署在多个机器上,一个down掉了,其他的还可以运行,对吧?” 张大胖一点就透。

Bill 赞许地点点头:“你想好怎么去实现了吗?”

“很简单啊,把定时调度系统部署到多个机器上,形成几个备份就行了!”

张大胖还在白板上画了这么一个图:

640?wx_fmt=png

“那同一个时刻,有多少个Scheduler 在运行?”  Bill 终于抛出了重磅炸弹。

张大胖现在明白Bill的疑问了了,三个实例都在运行,那一个Job就有可能运行多次,这肯定是不行的!

他说道:“要不让三个实例A,B,C都去访问同一个数据库吧!”

640?wx_fmt=png

Bill说:“那三个实例访问同一份数据,肯定会出现冲突,互相覆盖,那就乱套了!”

其实,实例A,实例B,实例C组成一个类似集群的东西,但是同一时刻,一个Job只能在一个实例上运行。

比如Job X 从凌晨1点开始,每隔1小时运行一次,那1:00 的时候Job X可能在实例A上运行, 2:00的时候可能在实例B上运行, 3:00的时候可能在实例C上运行。

也就是说,这三个实例部分地实现了负载均衡。

张大胖说:“这可就难办了。难道让这三个实例A,B,C之间互相通信?”

Bill说道:“那样有点麻烦,就变成一个分布式系统下的通信问题了,我们要不用这个数据库做点文章? 反正这个数据库已经存了Job的信息,Trigger的信息,我们就多加一个表吧,就叫LOCKS,这个表里边每一行记录都可以当做一个‘锁’来用。”

张大胖表示不太明白。

“很简单,就是数据库的‘行’锁嘛, 比如SELECT * FROM LOCKS where LOCK_NAME='TRIGGER' FOR UPDATE ,这就把那一行记录给锁住了, 别的事务只能等待当前事务commit以后才能访问。”

张大胖还是不太明白。

“比如,服务器A的实例A在一个事务中先执行了上面SQL, 就把那一行给锁住了,当服务器B的实例B也去执行同样的SQL的时候, 只能等待,对吧? 这不就相当于实例A获得了锁吗?”

“原来如此,以后任何一个调度器实例想要获取Job的运行时间,设置Job的下一次运行时间的时候,都必须先获得这个锁。这样这些分布式的调度器就不会冲突了,只会运行一个特定时间的Job。 我这就去做个详细设计,再来汇报。”

开源

两个月后,“大胖定时任务调度系统 3.0” 开发完毕,在Bill的大力支持和推动下,成功地应用在了公司的项目中。

灵活的设计和扩展性,加上持久化,集群等强大的功能, 系统受到了大家的欢迎。

考虑到很多公司都会有类似的需求,Bill决定把系统开源, 只是“大胖定时任务调度系统”这个名字有点俗,还有点长,Bill把它改名为“Quartz”。

Quartz从此流行开来。

(注:本文试图讲解Quartz的原理,其中的类图并没有和Quartz的真实类完全对应,这一点请大家知晓。)

(完)

你看到的只是冰山一角, 更多精彩文章,请移步《2016文章精华》或者《2017文章精华》


码农翻身

用故事讲述技术

640?wx_fmt=jpeg

Unity学习笔记3:随机数和动画脚本 Random的几个典型应用介绍如下。 1.随机数的获取:Random.Range(0,array.Length);在0到array.Length-1之间随机取一个数。在数组(比如说,物品数组)myArray中随机取一个数(随机取一件物品): var index = Random.Range(0, myArray.Length); myArray[index]; 2.不同概率随 阅读详情

相关推荐

任务调度系统的设计浅析

序言 系统所提供的功能,抽象起来是谁、在何时、做什么事情(who\when\what),具体到系统实现,分别是用户管理、任务管理、业务处理三个部分,本文主要归纳调度系统的重要组成部分,并给出方案设计的一般原则。 名词解释 调度系统模块 数据流分析 方案设计原则 一、名词解释 交易:完成特定业务目标的处理流程,比如一笔入账、一笔出账 任务:具有相同属性交易的集合,无论是OLTP还是OLAP交易,都可以包装成任务的形式,系统以任务驱动 二、调度系统模块 任务管理:任务生命周期管理(新建、启动、执行、结束)

weixin_43889339的博客 1401

Quartz从学习到踩坑到成功使用

Quartz从学习到使用Quartz的功能Quartz的实现对于Quartz任务增删改的封装方法无法在Job实现类中使用@Autowired注入Servivce的解决方案Quartz使用的封装类Quartz封装类的使用示例 Quartz的功能 Quartz是一个开源的定时作业框架,它可以用来定时去执行多个任务,只要按约定好的规则保存好Job和Trigger的相关参数,就可以非常方便直观地去控制任务...

Chrisz 569

游戏中的常见概率设计分析

前言游戏中的概率真的是让人又爱又恨,很多玩家因为自己的屌丝气质(白嫖)而弃坑玩不下去的,比如人尽皆知的某阴阳师,除了氪金,还肝,而且如果你的脸真的非常的黑,那也是打不过那些...

yolo模型训练找我,AI游戏合作找我 5999

从读写分离到CQRS,张大胖是如何解决性能问题的?

1不堪重负的数据库张大胖公司的数据库已经不堪重负了。 这个系统最早是两个实习生写的, 按照最初的设计,只是内部用户玩的, 大家可以把一些闲置不用的东西放在上面做交换, ...

码农翻身 473

任务调度系统简介及实例代码

本文介绍了任务调度系统的基本概念,并给出了一个简单的Python实例代码,帮助读者更好地理解任务调度系统的工作原理。本文将介绍任务调度系统的基本概念,并给出一个简单的实例代码,以帮助读者更好地理解任务调度系统的工作原理。任务调度器(Task Scheduler):任务调度器是任务调度系统的核心组件,负责接收任务请求、管理任务队列,并根据一定的策略选择合适的时间和资源来执行任务。任务队列(Task Queue):任务队列是用来存储待执行的任务的数据结构,通常采用先进先出(FIFO)的方式来管理任务。

KrDebugging的博客 344

基于java的任务调度系统设计与实现

基于Java的任务调度系统是一种用于管理和执行定时任务、周期性任务和异步任务的软件系统。性能评估是对系统在特定工作负载下的响应速度和资源利用率进行评估和分析,旨在验证系统是否能够满足用户在实际使用中的性能需求。以下是对基于Java的任务调度系统的性能评估的总结和分析:1、响应速度评估:响应速度是指系统对用户请求的响应能力。通过测量系统对用户请求的处理时间,评估系统的响应速度。可以测试不同功能的响应时间,如任务添加、编辑、删除和执行等操作的响应时间。

biyesheji1000的专栏 1078

分布式任务调度系统分析

分布式任务调度设计实践: 分析了一个定时任务调度最简单的架构,开源系统XXX-Job 代码

CoLiuRs 1838

从零开始搭建水质监测系统:STM32+Lora+4G的物联网应用详解

本文详细介绍了如何从零开始搭建一个基于STM32、LoRa和4G技术的工业级水质监测物联网系统。文章深入剖析了系统架构设计、核心硬件选型(如STM32F103系列MCU)、关键电路接口、嵌入式软件驱动开发、多任务调度以及云端数据集成与可视化的完整实战流程,为智慧农业、环境监测等领域的物联网应用提供了宝贵的“避坑指南”和解决方案。

m0n1o2p的博客 584

什么是任务调度

我们可以先思考一下业务场景的解决方案: 某电商系统需要在每天上午10点,下午3点,晚上8点发放一批优惠券。 某银行系统需要在信用卡到期还款日的前三天进行短信提醒。 某财务系统需要在每天凌晨0:10结算前一天的财务数据,统计汇总。 12306会根据车次的不同,设置某几个时间点进行分批放票。 某网站为了实现天气实时展示,每隔10分钟就去天气服务器获取最新的实时天气信息。 以上业务场景的解决方案就是任务调度。 任务调度是指系统为了自动完成特定任务,在约定的特定时

Leon_Jinhai_Sun的博客 8558

Ubuntu更新后VirtualBox报错rc=-1908?手把手教你修复Kernel driver not installed

本文详细解析了Ubuntu更新后VirtualBox报错rc=-1908的原因,并提供了完整的修复方案。通过重新安装VirtualBox、处理DKMS内核模块以及解决Secure Boot问题,帮助用户快速恢复虚拟机功能。特别针对Kernel driver not installed错误,给出了从诊断到修复的详细步骤。

weixin_42519781的博客 340

SRAM Bank数量配置:性能、面积与功耗的权衡指南

SRAM(静态随机存取存储器)是芯片设计中的关键存储单元,其Bank数量配置直接影响访问延迟、吞吐率、功耗和面积。Bank切分通过将存储阵列分区,缩短位线和字线延迟,从而提升性能,但会增加外围电路开销。合理配置Bank数量可优化PPA(性能、功耗、面积),在28nm和16nm工艺下,2个Bank通常是性价比最高的选择。本文基于实测数据,探讨不同场景下的Bank配置策略,帮助工程师避免常见误区,提升设计效率。

weixin_27230891的博客 179

如何给扑克洗牌才能更公平?

如何给扑克牌洗牌才能更显公平性前言一、需求分析 - 洗牌问题二、实现版本1. 版本一:常规思维2. 版本二:验证公平性3. 版本三:交换法则三、在线Online四、结束语往期推荐 前言 平常在日常生活中,我们总会遇到公平性这个话题。比如,几个人分奖品,怎么样才能公平分配?又或者,年会来个抽奖转盘,怎么样才能让它更公平呢? 那在下面这篇文章呢,我们将谈论关于洗牌的公平性。一起来了解吧~ 一、需求分析 - 洗牌问题 有时候我们在闲暇之余可能会打

moandaylab 1519

别再乱删文件了!修复Print Spooler服务自动停止的3个关键检查点(附Win10/Win11实测)

本文深入解析Windows系统中Print Spooler服务自动停止的常见原因及修复方法。从第三方驱动冲突、权限与服务依赖关系到打印队列积压,提供3个关键检查点的详细排查步骤,帮助用户彻底解决打印服务异常问题,适用于Win10/Win11系统。

weixin_31569671的博客 680

【游戏概率】☀️ 游戏中的常见概率设计分析,游戏概率常用算法整理

概率 在游戏中可以说是最玄学的东西了,只要涉及到游戏,基本上就跟概率是离不开关系的。 例如游戏中抽卡、开宝箱、抽奖等等玩法,说到底就是使用 概率 在操控。 比如原神中的祈愿,十连出4星,90发小保底,180发大保底都是在原有概率的基础上增加了一些可控的因素让玩家欲罢不能。

努力前行,总会成为自己心中的那道光 3万+

项目管理——14规划绩效域论文套路

规划绩效域论文套路

Flee Elf 1153

【第三只眼:Oracle通过归档日志查看系统的业务高峰sql】

根据oracle归档的业务高峰量,查找业务sql,进行优化

霍然的专栏 579

卡牌大师:玩转“洗牌算法”,幸运女神在微笑 (*^_^*)

我们目前的世界仍是基于 P ≠ NP,所以有理由相信:只要我们把牌洗的足够乱,幸运女神或许就会降临。(生活就像英雄联盟,运气游戏而已~) 本篇带来的就是:如何把牌洗的足够乱的 洗牌算法 ! 从青铜到王者,面试和实战都用得到! 点赞收藏 ✨ 闲言少叙,直接奥力给!! 青铜洗牌 ???? 题目:给你一副崭新的扑克牌(54 张),你如何 “洗乱” 它?? 咱青铜玩家通常很暴躁! 不就是洗牌嘛!聪明的青铜玩家,先将问题抽象为算法模型! 问题转化为: 已知:一个数组 nums = [1,2,3,

weixin_48424031的博客 1013

ZYNQ Linux环境下PS端I2C驱动OV5640摄像头全流程解析

本文详细解析了在ZYNQ Linux环境下,通过PS端I2C驱动OV5640摄像头的完整流程。内容涵盖从Vivado硬件配置、PetaLinux系统构建、设备树节点添加,到用户空间I2C编程与寄存器配置实战,并提供了关键的调试技巧与常见问题排查方法,帮助开发者快速实现嵌入式视觉应用的传感器配置。

vulkan6gpu的博客 853

任务调度(定时任务)

任务调度、Java常见的任务调度方式、任务调度的问题、分布式任务调度平台

一个什么都不会的人 7904

手把手教你用Keil5和Proteus8给51单片机跑个流水灯(附完整源码+安装包)

本文详细介绍了如何使用Keil5和Proteus8为51单片机实现流水灯效果,包括开发环境配置、汇编代码编写、电路设计及仿真调试。通过完整的源码和安装包,帮助初学者快速掌握C51单片机开发的核心流程,适合嵌入式开发入门学习。

weixin_42632434的博客 373

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

调度系统设计精要

作者 | Draveness 导读:本文作者写这篇文章前前后后大概 2 个月的时间,全文大概 2w 字,建议收藏后阅读或者通过电脑阅读。 调度是一个非常广泛的概念,很多领域都会使用调度这个术语,在计算机科学中,调度就是一种将任务(Work)分配给资源的方法。任务可能是虚拟的计算任务,例如线程、进程或者数据流,这些任务会被调度到硬件资源上执行,例如:处理器 CPU 等设备。 图 1&nb...

阿里巴巴云原生的博客 1053

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

任务调度系统就该这么设计(万能通用),稳的一批!

任务调度系统就该这么设计(万能通用),稳的一批!

LINgZone2的博客 3482

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

任务调度系统设计

字段字段类型说明idbigint作业 IDname作业名称作业描述job_typetinyint作业类型inputstext作业输入定义(json 格式)outputstext作业输出定义(json 格式)作业重试机制text作业成功条件contenttext作业执行内容id: Long1 -- Shell 脚本 2 -- Python 脚本 3 -- Http 请求 4 -- Sql 命令 5 -- Linux 命令。

u013803613的博客 2462

手把手教你自制任务调度系统

关注+星标公众号,不错过精彩内容转自| 大橙子疯嵌入式很多小伙伴用了很长时间的RTOS实时操作系统,但却对内核调度的机制原理一点不懂。不了解内核调度机制,可能在写应用代码的时候就会存在一些困惑,比如:CPU是怎么同时执行多个任务、多个任务之间到底有没有关联之类的困惑。今天手把手教你自制任务调度系统,从底层掌握相关的技术。1. 前言setjmp和longjmp是C语言标准库头文件中提供的函数。它们...

strongerHuang 956

20 张图告诉你,如何实现一个任务调度系统

阅读一篇「定时任务框架选型」的文章时,一位网友的留言电到了我: 我看过那么多所谓的教程,大部分都是教“如何使用工具”的,没有多少是教“如何制作工具”的,能教“如何仿制工具”的都已经是凤毛麟角,中国 软件行业,缺的是真正可以“制作工具”的程序员,而绝对不缺那些“使用工具”的程序员!...... ”这个业界最不需要的就是“会使用XX工具的工程师”,而是“有创造力的软件工程师”!业界所有的饭碗,本质就是“有创造力的软件工程师”提供出来的啊! 写这篇文章,想和大家从头到脚说说任务调度,希望大家读完之后,能.

qwer123451234123的博客 8156

【freeRTOS】操作系统之一-任务调度

freeRTOS 介绍

qq_15555275的博客 2816
上一篇: 一不小心冲到了第一
下一篇: 你如果只是一直囤干货,那永远不可能进步
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值