最近我在对项目的定时任务服务升级,希望改造成分布式,原本是利用@Scheduled注解实现,然而它并不支持分布式,如果改成quartz或者Spring Cloud Task,感觉对于自己这个简单的项目也没有必要。因此,我准备手写一个简单的支持分布式定时调度任务的框架。

项目地址是https://github.com/death00/dis-schedule,欢迎大家star、提意见。

分析

先分析了一下自己的项目,全都是用的cron表达式,因此执行时间点都是固定的,如果升级为分布式的话,肯定是希望在同一个时间点只有一个应用去执行定时调度。

场景就变成了:

多个应用在同一个时间都尝试去执行任务,但最终只有一个应用真正执行。

这样的话,立马就会让人联想到使用去解决,因为是多个应用,所以就是分布式锁。那么,场景又变了:

多个应用在同一个时间都尝试去获取分布式锁,只有一个应用能抢到这把锁,抢到锁的应用可以执行定时任务,其他应用则直接放弃,等待下一次执行时间。

抢锁的时机是每次定时任务执行之前,这又让我联想到了AOP,那么利用注解也就顺理成章了。

分布式锁

既然谈到了分布式锁,那么就想一下,这把锁的名称构成是什么。因为定时任务都有自己专门的时间,如果仅仅采用时间的话,那么当有两个任务同时执行时,则就是在抢一把锁,这同样是不合理的。

所以,锁的名称由两部分组成:任务执行时间、任务名称。

实现

实现方案其实已经很成熟了,可以利用Redis数据库Zookeeper等,Redis用的命令是setNx数据库一般都是利用的唯一索引Zookeeper这点我也不是很了解(如果有感兴趣的同学,欢迎在我的项目中添加)。

我的项目中实现了Redis数据库两种方式,可以看类DisScheduleRedisServiceImplDisScheduleMongodbServiceImpl

注解

其次,我自定义了一个注解DisSchedule

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DisSchedule {/*** 定时调度任务的名称(默认是方法名)*/String name() default "";/*** 任务的间隔时间*/int duration();/*** duration的时间单位(默认:分钟)*/DisScheduleUnit unit() default DisScheduleUnit.MINUTES;
}

  1. name代表此次定时调度任务的名称。
  2. duration代表任务的间隔时间,配合unit
  3. 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-分布式定时任务相关推荐

  1. scheduled线程池ScheduledExecutorService只执行一次_有个定时任务突然不执行了

    scheduled线程池ScheduledExecutorService只执行一次_有个定时任务突然不执行了 原因 If any execution of the task encounters an ...

  2. xxljob 配置具体定时任务_快速使用分布式定时任务 xxl-job

    快速使用分布式定时任务 xxl-job 需要linux服务器环境安装: jdk1.8 ,docker 安装步骤地址 : linux快速安装jdk   . 在linux里安装docker 1.docke ...

  3. @scheduled只执行一次_SpringBoot第四篇:定时任务@Scheduled

    使用SpringBoot创建定时任务主要有三种创建方式: 1.基于注解(@Scheduled) 2.基于接口(SchedulingConfigurer)实际使用中我们往往想从数据库中读取指定时间来动态 ...

  4. java定时器只执行一次_面试阿里P6,却被MySQL难倒,二战阿里,挤进天猫团队(Java岗)...

    爱因斯坦说过"耐心和恒心总会得到报酬的",我也一直把这句话当做自己的座右铭,这句箴言在今年也彻底在我身上实现了. 每一个程序员都拥有一座大厂梦,我也不例外,去年面试阿里P6,竟然被 ...

  5. java定时器只执行一次_搞定Java并发:为什么说只有1种实现线程的方法?(下)...

    在 上一篇(戳下看前情) 中,徐大带我们详细论证了,所有实现线程的方式归根结底就是基于 Runnable 接口或继承 Thread 类.接下来,请徐大继续解释,为什么说这两种方式本质上是一种. 一. ...

  6. winform 让他间隔一段时间 执行事件 且只执行一次_记一次golang定时器引发的诡异错误...

    作为一只在9127工作制下摸鱼的程序猿,周六自然是愉快的加班了.一早上除了一位新同学在我们的"敏捷迭代"下错删了接口之外没什么大事. 临近中午,突然隔壁组大佬找到我,表示有个go语 ...

  7. 如何让原本的密码只执行一次_如何在虚拟机中正确的第一次启动Linux系统

    在小编的上一篇文中,有介绍过如何在Virtualbox虚拟机中安装Linux CentOS系统,今天我们尝试第一次启动Linux系统,为保证虚拟机的流畅运行,建议将分辨率设置为 800x600. 1. ...

  8. C++中如何控制语句只执行一次_【Python基础(七)】逻辑控制

    本节将会讲到在编程中个人认为最重要的知识之一,逻辑控制.与其说是介绍语法,不如说是阐述看待事物的方法.我们身处的世界,每天有海量信息向我们袭来,每天我们要处理若干的事件,对于每一个事件,它都由若干个小 ...

  9. winform 让他间隔一段时间 执行事件 且只执行一次_米家智能插座改造:热水地暖(电热执行器、电磁阀类系统通用)接入米家...

    本文主要举例讲解将热水地暖改造后接入米家智能家庭. * 本文实际上在2020年1月底春节休假隔离时就已经编写完成,但因为小米蓝牙类温湿度计的"且"联动有bug,多个温湿度计的联合条 ...

最新文章

  1. 代码详解 | 用Pytorch训练快速神经网络的9个技巧
  2. 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高)...
  3. 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)...
  4. java蓝桥暑假班_Java实现 蓝桥杯VIP 算法提高 班级排名
  5. oracle单节点加入rac,实验:Oracle单节点RAC添加节点
  6. 缺陷分析之缺陷引入与移除矩阵
  7. 数据结构面试常见问题总结
  8. AutoCAD Civil 3D-部件-部件编辑器自定义边坡与材质
  9. 海瑞——一个奇特的人
  10. 狂神SpringBoot静态资源文件
  11. Grand Prix of Saratov - D. Elevator - DP
  12. 成功的自动化测试:测试员的故事
  13. (三十三)远期利率协议的结算金、价值与定价
  14. Linux CRDA(Central Regulatory Domain Agent)简介
  15. 怎么提取PDF页面,PDF页面提取的操作步骤
  16. mysql 2008降序排列_sql 升序降序排列
  17. (生物信息学)R语言绘图初-中-高级——3-10分文章必备——Venn图(韦恩图)(初级)
  18. 【LeetCode 1000】 Minimum Cost to Merge Stones
  19. 计算机组织电脑义诊是什么,计科院计算机协会开展电脑义诊活动
  20. 如果你一再做出错误的决定,很可能是认知出问题了

热门文章

  1. python如何运用到财务工作中存在的问题_财务工作存在问题及整改措施
  2. C语言(初遍学的一些零乱笔记)
  3. SAP 电商云 Spartacus 5_0.md 迁移文档的编写格式
  4. 经过 Webpack 处理过的 SAP Spartacus main.js
  5. SAP Spartacus的persist focus
  6. ABAP 740里的新语法 - LET表达式
  7. 如何替换Maven下载依赖时使用的仓库地址
  8. 使用ABAP绘制可伸缩矢量图
  9. SAP UI5 Fiori flower动画效果的实现明细
  10. Fiori Launchpad etag retrieve logic - UI5 Repository