一套代码中的定时任务被多个机器运行,数据容易变多或变大的解决办法。分布式锁,代码执行时间

一套代码中的定时任务被多个机器运行,数据容易变多或变大的解决办法。分布式锁,代码执行时间
开发中遇到了这样的一个场景,同一套代码在多台机器运行。奇葩的是数据库表都是同一个。由于业务需要写了很多定时任务来批量处理数据。但是在运行过程中发现,当多台机器同时运行同一套代码对同一个数据源操作同一个表的时候会出现跑出来的数据比正式数据要打,或者要多,这个时候就想到了要用锁。
但是单纯的锁只能锁住仅在一台机器运行时并发请求线程的问题(定时任务不仅可以定时运行还可以手动触发运行)。并不能解决问题,这时就要用到分布式锁了。可以用redis的分布式锁。
步骤,代码如下,不多解释

<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.16.3</version>
   -- 版本按自己需求
</dependency>

步骤一:注入(前提是有没有redis依赖)
在这里插入图片描述
步骤二:代码中运用

@Scheduled(cron = "0 59 23 * * ?")
    public void stockAllCityJob(){
        String lockey = "stockAllCityJob_stockExchange_lock";
        RLock lock = redissonClient.getLock(lockey);
        long starttime = System.currentTimeMillis();
        try {
            if(!lock.tryLock(0,10, TimeUnit.MINUTES)){
                log.warn("获取任务锁失败,退出。");
                return;
            }
            log.info("==================================定时任务开始=========================================================");
            //业务代码放在这里
            log.info("==================================定时任务结束=========================================================");
            
            long endtime = System.currentTimeMillis();
            long end =  endtime- starttime;
            System.out.println("定时任务执行时间:"+end / 1000 / 60 / 60 + "时" + end / 1000 / 60 % 60 + "分" + end / 1000 % 60 + "秒");

        } catch (InterruptedException e) {
            log.warn("获取任务锁异常,退出。");
            return;
        }finally {
            if(lock.isLocked() && lock.isHeldByCurrentThread()){
                lock.unlock();
                log.info(Thread.currentThread().getName() + "unlock");
            }
        }

    }

加入分布式锁后不论几台机器几个线程同时运行,最后只能运行最先抢到线程拿到锁的那个任务。

====更新=
解决此类问题还有一个方法,即:代码在多台机器上运行定时任务的时候可以指定定时任务在哪一个服务器ip上才可以运行
这样也可以解决类似的数据问题。
获取当前服务器ip的方法如下
在这里插入图片描述
具体代码:

public static void main(String[] args) {

        try {
            String hostAddress = InetAddress.getLocalHost().getHostAddress();
            System.out.println(hostAddress);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

注:此方法仅为个人思路并没有经过项目实际验证过,如有需要仅供参考。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值