scheduled只执行一次_升级@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
。
总结
以上就是我实现的简单的分布式定时任务,虽然简单,但应该可以满足你的基础需求,接下来,我会在这个之上,逐步增加功能(比如监测、失败后预警等)。如果你有什么想法,欢迎在下方留言。
有兴趣的话可以访问我的博客或者关注我的公众号、头条号,说不定会有意外的惊喜。
https://death00.github.io/
scheduled只执行一次_升级@Scheduled-分布式定时任务相关推荐
- scheduled线程池ScheduledExecutorService只执行一次_有个定时任务突然不执行了
scheduled线程池ScheduledExecutorService只执行一次_有个定时任务突然不执行了 原因 If any execution of the task encounters an ...
- xxljob 配置具体定时任务_快速使用分布式定时任务 xxl-job
快速使用分布式定时任务 xxl-job 需要linux服务器环境安装: jdk1.8 ,docker 安装步骤地址 : linux快速安装jdk . 在linux里安装docker 1.docke ...
- @scheduled只执行一次_SpringBoot第四篇:定时任务@Scheduled
使用SpringBoot创建定时任务主要有三种创建方式: 1.基于注解(@Scheduled) 2.基于接口(SchedulingConfigurer)实际使用中我们往往想从数据库中读取指定时间来动态 ...
- java定时器只执行一次_面试阿里P6,却被MySQL难倒,二战阿里,挤进天猫团队(Java岗)...
爱因斯坦说过"耐心和恒心总会得到报酬的",我也一直把这句话当做自己的座右铭,这句箴言在今年也彻底在我身上实现了. 每一个程序员都拥有一座大厂梦,我也不例外,去年面试阿里P6,竟然被 ...
- java定时器只执行一次_搞定Java并发:为什么说只有1种实现线程的方法?(下)...
在 上一篇(戳下看前情) 中,徐大带我们详细论证了,所有实现线程的方式归根结底就是基于 Runnable 接口或继承 Thread 类.接下来,请徐大继续解释,为什么说这两种方式本质上是一种. 一. ...
- winform 让他间隔一段时间 执行事件 且只执行一次_记一次golang定时器引发的诡异错误...
作为一只在9127工作制下摸鱼的程序猿,周六自然是愉快的加班了.一早上除了一位新同学在我们的"敏捷迭代"下错删了接口之外没什么大事. 临近中午,突然隔壁组大佬找到我,表示有个go语 ...
- 如何让原本的密码只执行一次_如何在虚拟机中正确的第一次启动Linux系统
在小编的上一篇文中,有介绍过如何在Virtualbox虚拟机中安装Linux CentOS系统,今天我们尝试第一次启动Linux系统,为保证虚拟机的流畅运行,建议将分辨率设置为 800x600. 1. ...
- C++中如何控制语句只执行一次_【Python基础(七)】逻辑控制
本节将会讲到在编程中个人认为最重要的知识之一,逻辑控制.与其说是介绍语法,不如说是阐述看待事物的方法.我们身处的世界,每天有海量信息向我们袭来,每天我们要处理若干的事件,对于每一个事件,它都由若干个小 ...
- winform 让他间隔一段时间 执行事件 且只执行一次_米家智能插座改造:热水地暖(电热执行器、电磁阀类系统通用)接入米家...
本文主要举例讲解将热水地暖改造后接入米家智能家庭. * 本文实际上在2020年1月底春节休假隔离时就已经编写完成,但因为小米蓝牙类温湿度计的"且"联动有bug,多个温湿度计的联合条 ...
最新文章
- 代码详解 | 用Pytorch训练快速神经网络的9个技巧
- 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高)...
- 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)...
- java蓝桥暑假班_Java实现 蓝桥杯VIP 算法提高 班级排名
- oracle单节点加入rac,实验:Oracle单节点RAC添加节点
- 缺陷分析之缺陷引入与移除矩阵
- 数据结构面试常见问题总结
- AutoCAD Civil 3D-部件-部件编辑器自定义边坡与材质
- 海瑞——一个奇特的人
- 狂神SpringBoot静态资源文件
- Grand Prix of Saratov - D. Elevator - DP
- 成功的自动化测试:测试员的故事
- (三十三)远期利率协议的结算金、价值与定价
- Linux CRDA(Central Regulatory Domain Agent)简介
- 怎么提取PDF页面,PDF页面提取的操作步骤
- mysql 2008降序排列_sql 升序降序排列
- (生物信息学)R语言绘图初-中-高级——3-10分文章必备——Venn图(韦恩图)(初级)
- 【LeetCode 1000】 Minimum Cost to Merge Stones
- 计算机组织电脑义诊是什么,计科院计算机协会开展电脑义诊活动
- 如果你一再做出错误的决定,很可能是认知出问题了
热门文章
- python如何运用到财务工作中存在的问题_财务工作存在问题及整改措施
- C语言(初遍学的一些零乱笔记)
- SAP 电商云 Spartacus 5_0.md 迁移文档的编写格式
- 经过 Webpack 处理过的 SAP Spartacus main.js
- SAP Spartacus的persist focus
- ABAP 740里的新语法 - LET表达式
- 如何替换Maven下载依赖时使用的仓库地址
- 使用ABAP绘制可伸缩矢量图
- SAP UI5 Fiori flower动画效果的实现明细
- Fiori Launchpad etag retrieve logic - UI5 Repository