分布式锁
什么是分布式
分布式结构就是将一个完整的系统,按业务功能,拆分成一个个独立的子系统,在分布式结构中,每个子系统就被称为”服务”。
在java中,synchronized关键词在我们的代码中是常见的,这些都是本地锁,只能解决一台服务器并发问题。
但随着业务增大,我们无法保证某个数据的改变是同一台服务器操作的。因此,我们需要一个能锁住所有服务器的锁—分布式锁。
使用Redis分布式锁,就需要用到Reddission客户端,它提供的功能远远超出了一个Redis客户端的范畴。在支持基本Redis功能的同时,提供了一些高级服务:
- 远程调用
- 分布式锁
- 分布式对象、容器
使用依赖:
<dependencies>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.13.0</version>
</dependency>
</dependencies>
装载一下对象
@Autowired
private RedissonClient redissonClient;
实现Redis分布式锁大致需要三步:
1.取得锁
RLock rLock = redissonClient.getLock("CUSTOM_NAME");
redissonClient.getLock()
得到一个 Redis 锁对象,方法参数是 字符串 类型的自定义锁名称,不一定要用数据 Key ,一般推荐用容易理解的、业务相关的名称。
CUSTOM_NAME 只是代码举例哦
为了减少冲突、明确含义、易于理解和维护,不要以简单的数字 id 值作为 Redis 中的数据 Key,推荐的格式是:
productId-1-stock
2.上锁
使用:
rLock.lock();
- 并发情况下,每个线程都会竞争锁:
- 竞争成功(获取锁)的线程会继续允许
- 竞争失败的线程会被禁用,并且重新获取锁之前,该线程将一直处于休眠状态。
简单说,抢不到锁的线程会持续等待,所有使用锁要特别小心
3.解锁
rLock.unlock();
有上锁就必然要解锁,否则会导致线程持续等等而产生死锁,系统也就卡死了。
所以,推荐把业务操作放在try–catch–finally中:
try {
rLock.lock();
// 抢购业务逻辑
} catch (Exception e) {
LOG.error("some error. ", e);
} finally {
rLock.unlock();
}