优化代码如下:

@Scheduled(cron = "${cs.task.cron.custtag.sync:0 0/15 * * * ? }") public void localRun() { Date beginDate = new Date(); log.info("localRun start currentTime={}", beginDate); String currentDate = DateUtil.formatDateYMDH(beginDate);

String lockKey = RedisKeyConstants.LOCK_KEY_PREFIX_ + "cust_tag_sync:" + currentDate;
Long currentSplit = null;
boolean lockAcquired = false;
try {
    // 尝试获取锁
    lockAcquired = RedisUtil.tryLock(lockKey, 60);
    if (!lockAcquired) {
        // 获取锁失败,分片已经被占用,直接返回
        log.warn("本地定时任务获取分片失败,分片已被占用,lockKey={}", lockKey);
        return;
    }
    currentSplit = RedisUtil.incrBy(lockKey, 1);
} finally {
    if (lockAcquired) {
        // 释放锁
        RedisUtil.unlock(lockKey);
    }
}
try {
    TimeUnit.SECONDS.sleep(30);
    // 重新获取分片,确保获取到的值是最新的
    Long currentSplitFromRedis = RedisUtil.get(lockKey);
    if (currentSplit.equals(currentSplitFromRedis)) {
        // 分片数没有改变,可以处理数据
        runByOneDay(beginDate, currentSplit, currentSplitFromRedis);
    } else {
        // 分片数已经改变,可能有数据被漏掉,需要重新分配
        log.warn("本地定时任务分片数已经改变,currentSplit={}, currentSplitFromRedis={}", currentSplit, currentSplitFromRedis);
    }
} catch (InterruptedException e) {
    log.error("本地定时任务获取分片休眠失败", e);
}

}

优化后的代码通过Redis的分布式锁来保证只有一个实例能够获取到分片,避免了分片被重复占用的问题。同时,优化后的代码在处理数据之前重新获取分片数,确保获取到的值是最新的,避免了数据漏掉的问题。最后,释放锁的操作放在finally块中,确保即使出现异常也能够释放锁,避免死锁

在休眠失败的时候其他主机处理会导致漏一个分片的数据试着优化下面的代码解决这个问题以及怎么保证最后每台实例拿到的RedisUtilgetlockKey值是一样的?否则会导致数据重复处理Scheduledcron = $cstaskcroncusttagsync0 015 public void localRun Date beginDate = new Date;

原文地址: https://www.cveoy.top/t/topic/g0Ac 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录