升级@Scheduled-分布式定时任务
最近我在对项目的定时任务服务升级,希望改造成分布式,原本是利用@Scheduled注解实现,然而它并不支持分布式,如果改成quartz或者Spring Cloud Task,感觉对于自己这个简单的项目也没有必要。因此,我准备手写一个简单的支持分布式定时调度任务的框架。
项目地址是https://github.com/death00/dis-schedule,欢迎大家star、提意见。
分析
先分析了一下自己的项目,全都是用的cron表达式,因此执行时间点都是固定的,如果升级为分布式的话,肯定是希望在同一个时间点只有一个应用去执行定时调度。
场景就变成了:
多个应用在同一个时间都尝试去执行任务,但最终只有一个应用真正执行。
这样的话,立马就会让人联想到使用锁去解决,因为是多个应用,所以就是分布式锁。那么,场景又变了:
多个应用在同一个时间都尝试去获取
分布式锁,只有一个应用能抢到这把锁,抢到锁的应用可以执行定时任务,其他应用则直接放弃,等待下一次执行时间。
抢锁的时机是每次定时任务执行之前,这又让我联想到了AOP,那么利用注解也就顺理成章了。
分布式锁
既然谈到了分布式锁,那么就想一下,这把锁的名称构成是什么。因为定时任务都有自己专门的时间,如果仅仅采用时间的话,那么当有两个任务同时执行时,则就是在抢一把锁,这同样是不合理的。
所以,锁的名称由两部分组成:任务执行时间、任务名称。
实现
实现方案其实已经很成熟了,可以利用Redis、数据库、Zookeeper等,Redis用的命令是setNx,数据库一般都是利用的唯一索引,Zookeeper这点我也不是很了解(如果有感兴趣的同学,欢迎在我的项目中添加)。
我的项目中实现了Redis、数据库两种方式,可以看类DisScheduleRedisServiceImpl、DisScheduleMongodbServiceImpl。
注解
其次,我自定义了一个注解DisSchedule,
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DisSchedule {
/**
* 定时调度任务的名称(默认是方法名)
*/
String name() default "";
/**
* 任务的间隔时间
*/
int duration();
/**
* duration的时间单位(默认:分钟)
*/
DisScheduleUnit unit() default DisScheduleUnit.MINUTES;
}
name代表此次定时调度任务的名称。duration代表任务的间隔时间,配合unit。unit是自定义的时间单位,有秒、分钟。
该注解需要配合@Scheduled共同使用,例如:
@DisSchedule(name = "testSchedule", duration = 1, unit = DisScheduleUnit.MINUTES)
@Scheduled(cron = "0 0/1 * * * ?")
该cron表达式代表1分钟执行一次,且是在整数分钟开始的时候执行,因此@DisSchedule也需要设置为1分钟的时间。
切面
接下来,我们只需要在Aspect中定义好切入点(有注解@DisSchedule的方法上),针对这些方法,需要使用Around(环绕增强)进行拦截,因为当抢不到锁的时候,就不允许执行。
具体可以参考类DisScheduleAspect。
总结
以上就是我实现的简单的分布式定时任务,虽然简单,但应该可以满足你的基础需求,接下来,我会在这个之上,逐步增加功能(比如监测、失败后预警等)。如果你有什么想法,欢迎在下方留言。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。


升级@Scheduled-分布式定时任务的更多相关文章
- 【redis】分布式锁实现,与分布式定时任务
如果你还不知道redis的基本命令与基本使用方法,请看 [redis]redis基础命令学习集合 写在前面 redis辣么多数据结构,这么多命令,具体一点,都可以应用在什么场景呢?用来解决什么具体的问 ...
- springboot整合xxl-job分布式定时任务【图文完整版】
一.前言 定时任务有很多种,有一些大的框架也有一些简单的实现. 比如常见的: JDK的Timer和TimerTask Quartz异步任务调度框架 分布式定时任务XXL-JOB Spring Task ...
- spring的Scheduled(定时任务)和多线程
一.前言 在我们日常的开发中,经常用到数据同步的更新,这时我们采用的是spring的定时任务和java的多线程进行数据的更新,进行时实的服务调用. 二.实现思路 1.创建线程类 ...
- 基于spring+quartz的分布式定时任务框架
问题背景 我公司是一个快速发展的创业公司,目前有200人,主要业务是旅游和酒店相关的,应用迭代更新周期比较快,因此,开发人员花费了更多的时间去更=跟上迭代的步伐,而缺乏了对整个系统的把控 没有集群之前 ...
- spring注解scheduled实现定时任务
只想说,spring注解scheduled实现定时任务使用真的非常简单. 一.配置spring.xml文件 1.在beans加入xmlns:task="http://www.springfr ...
- 分布式定时任务框架比较,spring batch, tbschedule jobserver
分布式定时任务框架比较,spring batch, tbschedule jobserver | 移动开发参考书 分布式定时任务框架比较,spring batch, tbschedule jobser ...
- lesson9:分布式定时任务
在实际的开发过程中,我们一定会遇到服务自有的定时任务,又因为现在的服务都是分布式的,但是对于定时任务,很多的业务场景下,还是只希望单台服务来执行,网上有很多分布式定时任务的框架,各位如感兴趣,可以自行 ...
- 分布式定时任务 -- elastic-job
一.前言 在我们的项目当中,使用定时任务是避免不了的,我们在部署定时任务时,通常只部署一台机器.部署多台机器时,同一个任务会执行多次.比如短信提醒,每天定时的给用户下发短信,如果部署了多台,同一个用户 ...
- 分布式定时任务框架——python定时任务框架APScheduler扩展
http://bbs.7boo.org/forum.php?mod=viewthread&tid=14546 如果将定时任务部署在一台服务器上,那么这个定时任务就是整个系统的单点,这台服务器出 ...
- 【xxl-job】轻松实现分布式定时任务demo实例
[项目描述]前段时间专门独立了一个spring boot服务,用于做和第三方erp系统的对接工作.此服务的第一个需求工作就是可以通过不同的规则,设置不同的定时任务,从而获取erp系统的商品数据.所以, ...
随机推荐
- F-maximum clique 1_2019牛客暑期多校训练营(第五场)
题意 给出n个不同的数字\(a_i\),求出最大的子集,使得子集内任意两个数在二进制下至少有两位不同. 题解 先对任意两个二进制位只有一个不同的两个数连边,那么问题就转化成找出最多的点集,任意两点没有 ...
- 【CF #541 D】 Gourmet choice
link:https://codeforces.com/contest/1131 题意: 给定一些大小比较,输出排名. 思路: 这道题我用的是拓扑排序,又因为有等于号的存在,我用了并查集. 结束后这道 ...
- POJ - 3436 ACM Computer Factory 网络流
POJ-3436:http://poj.org/problem?id=3436 题意 组配计算机,每个机器的能力为x,只能处理一定条件的计算机,能输出特定的计算机配置.进去的要求有1,进来的计算机这个 ...
- HihoCoder - 1617 方格取数
HihoCoder - 1617 (从群主那里借鉴来的, 群主好强啊) 题意:中文题不解释... 题解: dp[X][i][j] 代表的是X是坐标之和 第一个人 走到位置 dp[i][x-i] 第二个 ...
- codeforces 779 D. String Game(二分)
题目链接:http://codeforces.com/contest/779/problem/D 题意:给你一段操作序列,按顺序依次删掉字符串1中相应位置的字符,问你最多能按顺序删掉多少个字符,使得s ...
- 基于 APIGateway 打造生产级别的 Knative 服务
作者 | 阿里云智能事业群高级开发工程师 元毅 导读:在实际应用中,通过 APIGateway(即 API 网关),可以为内部服务提供保护.提供统一的鉴权管理.限流.监控等能力,开发人员只需要关注内 ...
- 【Offer】[47] 【礼物的最大价值】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 在一个m*n的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于0).你可以从棋盘的左上角开始拿格子里的礼物,并每次向左(以自 ...
- Redis的那些最常见面试问题(转)
Redis的那些最常见面试问题 1.什么是redis? Redis 是一个基于内存的高性能key-value数据库. 2.Reids的特点 Redis本质上是一个Key-Value类型 ...
- Log4Net 日志记录的实现
一.前言 在上一篇文章[(转载)非常完善的Log4net配置详细说明]介绍了Log4Net的配置说明,如果不知道的可以去看看,这里我们就介绍一下日志记录的实现,说得都比较基础,所以大神请绕过. 二.L ...
- ViewGroup和View
ViewGroup本身表示容器, 他是View的一个抽象子类, 它可以包含很多个普通的view组件,另外它还可以包含一个ViewGroup容器. 由于它是一个抽象类,所以实际使用中通常使用viewGr ...