springboot 分布式定时任务调度 zookeeper + AOP实现

Scheduled 定时任务的问题

定时任务,是很多业务系统都需要用到的东西,在Springboot中,我们通常用@Scheduled注解去定义一个单体应用定时任务。然而在微服务的场景下还使用这个东西,定时任务就会重复执行了。就比如我向下面这样定义了一个定时任务(每分钟的0,5,10…秒都会执行),然后修改端口启动两次应用,不用猜,自然是两个进程都重复执行了。

	@Scheduled(cron = "*/5 * * * * ?")
    public void MySchedule2(){
   
        try{
   
            logger.info("[DistributedScheduled service port:{}] 执行定时任务 ....",port);
            Thread.sleep(4000);
        } catch (InterruptedException e) {
   
            e.printStackTrace();
        }
    }

在某些业务场景下定时任务重复执行,是会有问题的。比如说一个信用卡系统,每天早上八点扫描自己的欠钱的用户来发催还款的短信。大家可以想想,如果你是一个信用卡用户,它每次催缴短信都是三连发,是不是烦的一批(至少我是这样)。当然,我们可以给业务表加一些字段来标志它是否推送过短信解决这个问题,但是这么做,定时任务的逻辑侵入业务了,增加了业务表的复杂性,这种事情当然是不想干的。

有没有什么好办法呢?

我选择的方案是zookeeper给定时任务枷锁,来保证同一时刻只有一个服务会触发定时任务。每个服务在执行定时任务之前都要去判断自己能不能执行,具体而言,就是用定时任务名去zookeeper加锁,加锁成功才能执行。时序图如下:
分布式定时调度时序图

实现代码

下面部分主要是代码,首先是启动类,注意要加上EnableScheduling 开启定时任务,否则不会执行:

@SpringBootApplication
@EnableScheduling   // 2.开启定时任务
public class ApplicationBoot {
   
    public static void main(String[] args) {
   
        new SpringApplication(ApplicationBoot.class).run(args);
    }
}

下面是定义了一个包含定时任务信息的注解,主要可以拿来获取定时任务名。

import org.springframework.core.annotation.AliasFor;
import org.springframework.scheduling.annotation.Scheduled;
import java.lang.annotation.*;

@Target({
   ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值