防止多台机器上的 task 在同一时间一起执行,只要执行一个就可以了
import service.redis.RedisFacade;
/**
* Author: heatdeath
* Date: 2018/4/24
* Desc: 基于 Redis 实现的简易分布式锁
*/
public class DistributedLockUtil {
private String redisKey;
private static RedisFacade redisFacade;
private static final int IMMEDIATELY_EXPIRED_TIME = 0;
private static final int EXPIRE_TIME = 9 * 60;
/**
* 构造器,需要输入 redisKey
*
* @param redisKey the redis key
* @throws Exception the exception
*/
public DistributedLockUtil(String redisKey) throws Exception {
this.redisKey = redisKey;
redisFacade = RedisFacade.getInstance();
}
/**
* 使用 redis 的 setnx 命令尝试获取锁
* 如果成功获取,设置过期时间为 6 min,返回 true
* 如果失败,返回 false
*
* @return the boolean
* @throws Exception the exception
*/
public Boolean tryLock() throws Exception {
Boolean flag = redisFacade.setnx(redisKey, String.valueOf(System.currentTimeMillis())) == 1;
if (flag)
redisFacade.expire(redisKey, EXPIRE_TIME);
return flag;
}
/**
* 释放分布式锁,设置 key 的过期时间为 0s
*
* @throws Exception the exception
*/
public void release() throws Exception {
redisFacade.expire(redisKey, IMMEDIATELY_EXPIRED_TIME);
}
}
@Service
public class CountlogSendEmailTask {
@Autowired
private CountServiceItf countService;
private static final String REDIS_KEY = DistributedLockConst.LOCK_FOR_COUNT_BACK_LOG_EMAIL_TASK;
@Scheduled(cron = "0 0 * * * ?")
public void countBacklogSendEmail() throws Exception {
DistributedLockUtil distributedLock = new DistributedLockUtil(REDIS_KEY);
if (!distributedLock.tryLock())
return;
countService.countBacklogSendEmail();
distributedLock.release();
}
}
参考资料:
1、 使用Redis SETNX 命令实现分布式锁
https://blog.youkuaiyun.com/lihao21/article/details/49104695
2、 Java Jedis操作Redis示例(三)——setnx/getset实现分布式锁
https://blog.youkuaiyun.com/KingCat666/article/details/77892176
3、Redis 分布式锁的正确实现方式( Java 版 )
http://www.importnew.com/27477.html