主要用到redis的setIfAbsent设置key,它的特点是:如果key已经存在,则返回false,可表示未获取到锁,否则返回true,表示获取到锁;

另外,定时任务的锁比一般提交事务的锁简单一些,如果同一个定时任务的多个实例抢一把锁,抢不到锁的可以退出,等待下一个时间周期,自动实现了锁自旋的效果;

还有,在定时任务的业务循环内部加一个延长锁时间的设置。

Talk is cheap. Show me the code:

@Component
@Slf4j
public class JobService {
    @Autowired
    private XxxService xxxService;
    @Autowired
    private RedisUtil redisUtil;
    //每分钟执行一次的任务
    @Scheduled(cron = "0 */1 * * * ?")
    public void xxxJob() {
        String key = "job:xxxDelayedDelete";
        Integer timeout = 180;
        //此处需要引入redission锁
        boolean lock = redisUtil.setIfAbsent(key, 1, timeout);
        if (!lock) return;
        Date now;
        Integer total = 0;
        try {
            log.info("===========开始任务xxxDelayedDeleteJob===========");
            Integer size = 0;
            do {
                size = 0;              
                final List<Xxx> xxxnList = xxxService.list();
                if (xxxList != null && xxxList.size() > 0) {
                    size = xxxList.size();
                    total += size;
                    Integer ret;
                    for (Xxx xxx: xxxList) {
                        //延长分布式锁时间,防止过期
                        redisUtil.set(key, 1, timeout);
                        //业务代码……
                        ret = xxxService.delete(xxx.getId());
                    }
                }
            } while (size > 0);
        } catch (Exception ex){
            log.error("------xxxDelayedDeleteJob "+ex.getMessage()+"," + JSONUtil.toJsonStr(ex.getStackTrace())+"--------");
        }finally {
            //释放锁
            redisUtil.del(key);
        }
        log.info("===========结束任务xxxDelayedDeleteJob====处理数量:"+total+"=======");
    }
}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐