这是我参与「第三届青训营 -后端场」笔记创作活动的第六篇笔记
课程收获:
课程目录:
1 前言
春节集卡瓜分20亿
把分散的,可靠性差的计划任务纳入统一的平台,并实现集群管理调度和分布式部署的一种定时任务的管理方式,叫做分布式定时任务。
2 发展历程
2.1 Windows批处理
2.2 Windows计划任务程序
2.3 Linux命令--CronJob
2.4 单机定时
单机定时我这里分为纯单机版、 固定 IP 版、分布式锁版、单机调度版,下面从这四个角度来谈一谈他们的实现方式以及当时所在的背景。
纯单机版
顾名思义,就是应用都是单体应用,不存在集群,写一个定时任务就可以了,可以是线程定时调度、也可以是 Spring 定时框架用@Scheduled注解实现。这种方式在单体应用的极为合适,主要是简单方便。当然也存在他的弊端,那就是如果我的应用是多机部署的,那就会导致并发冲突。出现问题,解决问题,所以下面三种方式应运而生。
固定 IP 版
就是如果事先知道了机器的 IP 地址,并且基本上 IP 地址也不会变化,只需要在代码中写一个判断逻辑,这样 IP 地址不是当前机器的应用,并不会执行定时任务。这种方式可以很完美的避免多台机器同时执行定时任务,也可以稍微进阶一下,就是将指定的 IP 地址用 @Value 注解,然后可以在配置中心,比如 Apollo 进行动态修改。
分布式锁版
这种和上面的方式区别不大,只是在中间尝试获取分布式锁,不过需要对分布式锁的时间把握好,一般问题不大,如果一天一次的定时任务,在 Redis 锁它个一天都可以,总不能定时任务也执行一天。当然几分钟一次的也一个意思,合理安排锁的时间就行。在数据库写个标识也可以,都是大同小异。
单机调度版
这种方式也很容易理解,定时执行的任务,也是一个接口,定时去调度一下这个接口就行了。这种方式是完全可以的,定时系统用 Spring 定时框架定时执行,定时系统是单机的,不存在并发,调度到业务系统,可以使用 Dubbo,这里只会有一台机器被调度到。 这种情况也存在弊端,就是定时系统是单机的,如果他挂了怎么办?
2.4.1 单机定时命令--Timer,Ticker
2.4.2 单机定时任务--ScheduledExecutorService
2.5 任务调度--Quartz
2.6 分布式定时任务
定时任务,解决了自动化和准时这两个问题;
分布式定时任务,则是解决高性能、可靠性、分布式部署等问题;
2.6.1 特点
2.6.2 执行方式
2.7 业内定时任务框架
2.7.1 Xxl-job
2.7.2 schedulerX
2.7.3 TCT
2.8 知识面扩充
2.9 小结
3 实现原理
3.1 核心架构
并非所有的框架都有这四层结构,Xxl-job只有两层,schedulerX只有三层。
3.1.1 数据流
3.1.2 功能架构
3.2 控制台
3.2.1 基本概念
3.2.2 任务元数据
3.2.3 任务实例
通过Job_id和任务元数据所对应
3.3 触发器
3.3.1 核心职责
3.2.2 触发器--方案1
定时扫描的机器集群部署,通过分布式锁保证只有一台在调度。扫描到的任务要是还有一段时间才能运行,可以结合消息队列的技术来优化控制。
3.2.3 触发器--方案2
查询时不需要遍历整个链表,性能大大提升。但是任务多的时候内存消耗太大,空间开销难以接受。
类比于数据结构中循环队列的思想。但是需要考虑任务太多,刻度不够的任务的先后执行顺序的问题,于是有了下面的改进方法。
3.3.4 触发器--高可用
问题引出
数据库行锁模式
分布式锁的方式
3.4 调度器
调度器需要解决的问题:
3.4.1 资源来源
业务系统提供机器资源:即由负责开发业务的任务组提供所需要的资源;
定时任务平台提供机器资源:所需要的机器资源由负责定时任务的平台来提供;
3.4.2 资源调度
节点选择
任务分片
3.4.3 高级特性
任务编排
故障转移
3.4.4 调度器--高可用
3.5 执行器
调度中心要确保执行器出问题的时候,能将执行器中未执行的任务进行分发和继续执行。