–在以往我们做数据去重,或者业务隔离的时候,比如秒杀业务,商品下单,某些特定的功能在同一时间内只能一个线程进行,但线程多少个不是我们能控制的,大多数都是从代码入手,比如数据表加点唯一索引、使用乐观锁、去重校验,添加事务、等多种方式,在Java层面也有两个使用非常方便的锁概念,一个是synchronized、一个是Lock
synchronized 如:
// 同步代码块
synchronized (this){
// 代码块
}
/**
* 同步方法
*/
public synchronized void test(){
// 代码块
}
lock 如:
// 锁变量
Lock lock = new ReentrantLock();
/**
* 同步方法
*/
public void testA() {
lock.lock();
try {
// 代码块
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
这两种方式均能有效的对代码进行加锁,从而保证在同一时间,只有一个线程访问该代码,杜绝了数据错乱的问题
–当然这两种办法也有它的弊端,即只能在单体服务中生效,无法跨服务,集群部署时,则失效,仍然会出现问题、常见的有定时任务,广播消费,mqtt等,我们就需要考虑分布式的问题,这里我们采用RedissonClient分布式锁,使用非常方便,它采用Redis为底层架构,继承了Redis单线程的优点,内部方法均已封装,我们只需要调用即可,无需关心内部结构,非常简单,接下来开始上手~
第一步、添加POM
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.6</version>
</dependency>
第二步、注入对象
/**
* redis分布式锁
*/
@Autowired
private RedissonClient redissonClient;
第三步、上代码
/**
* 同步方法
*/
public void testB() {
// 获取分布式锁
RLock lock = redissonClient.getLock("lock:testBLock");
if (!lock.tryLock()) {
log.error("获取分布式锁失败");
return;
}
// 获取锁成功
try {
// 代码块
} catch (Exception e) {
e.printStackTrace();
} finally {
if (lock.isLocked()) {
lock.unlock();
}
}
}
第四步、运行(省略调用代码)
此时运行时redis中会在lock目录下存储testBLock的锁,代码运行完后会自动删除,从而实现了分布式集群部署加锁的问题,非常好用,赶快上手实验吧~
本次教程到这里就结束了,希望大家多多关注支持(首席摸鱼师 微信同号),持续跟踪最新文章吧~