主要用到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+"=======");
}
}