场景:其实原理是就是多台机器,去争抢一个资源,谁争抢成功,那么谁就持有了这把锁,然后去执行后续的业务逻辑,执行完毕后,把锁释放掉。
分布式锁的几种实现方式:
(1)利用数据库(mysql等),插入一条记录(唯一索引),谁插入成功,谁就持有锁,如果插入异常,捕捉异常,直接执行后续查询操作,就不需要再重复插入了,因为上一个事务已经创建成功了(已经测试成功);
(2)还可通过zookeeper来实现分布式锁,谁创建节点成功,谁就持有锁(目前还没有研究过)
(3)redis实现分布式锁 springboot启动类加@EnableScheduling注解,@Scheduled才会生效。setIfAbsent()方法就是redis命令里的setNX(已经测试成功)
/**
* @author: qiucheng
* @date: 2020-07-10 10:43
*/
@Component
public class BusinessTask {
private final static String LOCK_ID = "happyjava";
@Autowired
private DistributedLock distributedLock;
@Scheduled(cron = "0/10 * * * * ? ")
public void doSomething() {
System.out.println("轮询执行开始......");
boolean lock = distributedLock.getLock(LOCK_ID, 10 * 1000);
if (lock) {
System.out.println("执行任务");
distributedLock.releaseLock(LOCK_ID);
} else {
doSomething();
System.out.println("没有抢到锁");
}
}
}
@Component
public class DistributedLock {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 获得锁
*/
public boolean getLock(String lockId, long millisecond) {
Boolean success = redisTemplate.opsForValue().setIfAbsent(lockId, "lock",
millisecond, TimeUnit.MILLISECONDS);
return success != null && success;
}
/**
* 释放锁
* @param lockId
*/
public void releaseLock(String lockId) {
redisTemplate.delete(lockId);
}
}