分布式锁
###基本概念
我们在开发单体应用的时候,如果遇到多线程同步访问某个方法时,只需要非常简单的加锁处理即可保证数据的正确性,那如果集群部署的时候,比如在线上执行一个定时任务,两边同时执行了你的任务,导致数据错乱,甚至造成更大损失。那么分布式锁到底该用在哪些场景,分布式锁应该具备什么条件呢?
1.在分布式环境下,一个方法只能被其中一台机器单线程执行
2.锁要有可重入性
3.锁失效机制,防止死锁,如果获取不到锁,直接返回失败
###常用分布式锁
1.数据库分布式锁
这种锁,有一定的缺陷,首先是性能问题。其次需要写很多逻辑去处理,而且过程中会出现很多问题,实现方式:创建一张表,要使用就把方法名插入进数据库,从而获得锁,执行完成删除数据
2.redis 手动分布式锁 主要是NX的实现,过程比较复杂,释放锁,需要写lua脚本,不推荐
3.zookeeper分布式锁 更加复杂,不推荐
4.zookeeper的curator客户端 唯一的缺陷是基于zookeeper
这个写一下,毕竟好用
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
/***
*注册CuratorFramework
*/
@Component
public class CuratorLockConf {
@Bean(initMethod = "start",destroyMethod = "close")
public CuratorFramework getFramework(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181", retryPolicy);
return client;
}
}
@Autowired
private CuratorFramework client;
@RequestMapping("cc")
public String curatorLock(){
log.info("进入方法");
InterProcessMutex lock = new InterProcessMutex(client,"/order" );
try {
if (lock.acquire(30, TimeUnit.MINUTES)){
try {
log.info("获得了锁");
Thread.sleep(1000);
}finally {
log.info("释放了锁");
lock.release();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "Ok";
}
接下来是我们平时项目中用到最多的一种锁 redisson
5.redissonApi方式
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.3</version>
</dependency>
@RequestMapping("RedissonApiLock")
public String RedissonApiLock(){
Config config = new Config();
config.useSingleServer().setAddress("redis://192.168.1.200:9379").setPassword("root@123456").setDatabase(3);
RedissonClient redissonClient = Redisson.create(config);
RLock order = redissonClient.getLock("order");
log.info("进入了方法");
try {
order.lock(30,TimeUnit.SECONDS);//过期时间,如果没有释放锁,超出时间会自动释放
log.info("获得了锁");
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}finally {
log.info("释放了锁");
order.unlock();
}
return "Ok";
}
6.redisson-spring-boot-start 用到最多的方法
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.3</version>
</dependency>
@Autowired
private RedissonClient redissonClient;
@RequestMapping("RedissonLock")
public String RedissonLock(){
RLock order = redissonClient.getLock("order");
log.info("进入了方法");
try {
order.lock(30,TimeUnit.SECONDS);//过期时间,如果没有释放锁,超出时间会自动释放
log.info("获得了锁");
Thread.sleep(1000);
}catch (Exception e){
e.printStackTrace();
}finally {
log.info("释放了锁");
order.unlock();
}
return "Ok";
}