栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

java集群模式下解决定时任务重复执行的方案

Java 更新时间:发布时间: 百科书网 趣学号

1.默认固定执行定时任务的服务

在某一台服务上面执行定时任务,其他服务关闭定时任务,或者在定时任务前加判断指定ip,缺点指定的服务出现问题则定时任务无法在运行。

2.利用mysql共享锁事务管理机制运行任务

创建定时任务表,name为不同定时任务的指定名称,excute为是否执行中 1执行0未执行

 

由于存在表锁和行锁,因此同一时刻只能有一个事务操作,可以保证只执行一次。

此处更新操作只会成功一次,执行完重新设置excute为0;

   //基于mysql
    @Scheduled(cron = "0 * * * * ?")
    public void test1() throws UnknownHostException {
        
        boolean test = timingService.lambdaUpdate()
                .set(TimingB::getExcute, "1")
                .set(TimingB::getIp, InetAddress.getLocalHost().getHostAddress())
                .eq(TimingB::getName, "test")
                .eq(TimingB::getExcute,"0")
                .update();
        if (test==true){
            System.out.println("-----------定时任务开始执行------------");
            //...业务

            //重新设置回0
            timingService.lambdaUpdate()
                    .set(TimingB::getExcute, "0")
                    .eq(TimingB::getName, "test").update();
        }
    }

3.利用redis

执行定时任务前先查询 redis 是否有改任务的值,没有就自己 执行,并插入新的 key-value。有的话则不执行。

 //基于redis
    @Scheduled(cron = "0 * * * * ?")
    public void test2()  {

        //先走分布式锁
        boolean b = getLock("b", 5000, 10, 1000);
        //获得锁在判断
        if (b){
            String test = template.opsForValue().get("test");
            if (test==null){
                //定时任务为1分钟,过期时间设置50为秒
                template.opsForValue().set("test","test",50000L, TimeUnit.MILLISECONDS);
                System.out.println("-----------定时任务开始执行------------");

                //...业务
            }
        }
    }
    
    public boolean getLock(String lock, long timeout, long tryInterval, long lockExpireTime) {
        try {

            long startTime = System.currentTimeMillis();
            do{
                if (template.opsForValue().setIfAbsent(lock, lock, lockExpireTime, TimeUnit.MILLISECONDS)) {
                    return true;
                } else {//存在锁
                    log.debug("lock is exist!!!");
                }
                if (System.currentTimeMillis() - startTime > timeout) {//尝试超过了设定值之后直接跳出循环
                    return false;
                }
                Thread.sleep(tryInterval);
            }
            while (template.hasKey(lock)) ;
        } catch (InterruptedException e) {
            log.error(e.getMessage());
            return false;
        }
        return false;
    }

4.使用分布式任务调度框架

如Quartz、Xxl-job、Elastic-job等等。

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/957422.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号