主题
面试速答(先看这里)
**一句话结论:**关于Redisson实现分布式锁可以查看:
60秒标准回答:
在使用SETNX实现的分布式锁中,因为存在锁无法续期导致并发冲突的问题,所以在真实的生产环境中用的并不是很多,其实,真正在使用Redis时,用的比较多的是基于Redisson实现分布式锁
Redisson是一个基于Redis的Java客户端,它提供了丰富的功能,包括分布式锁的支持
关于Redisson实现分布式锁可以查看
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**在使用SETNX实现的分布式锁中,因为存在锁无法续期导致并发冲突的问题,所以在真实的生产环境中用的并不是很多,其实,真正在使用Redis时,用的比较多的是基于Redisson实现分布式锁。
- **要点2:**Redisson是一个基于Redis的Java客户端,它提供了丰富的功能,包括分布式锁的支持。
- **要点3:**为了避免锁超时,Redisson中引入了看门狗的机制,他可以帮助我们在Redisson实例被关闭前,不断的延长锁的有效期。
- **要点4:**基于Redisson可以非常简单的就获取一个可重入的分布式锁。
- **要点5:**以上方式,实现的是一个可重入的分布式锁,也就是说,获取到锁的线程可以再次尝试获取锁,并且这个锁也只能被这个线程解锁。
**记忆锚点:**Redisson → Redis → 个可重入的分布式锁 → redisson → https → redissonorg
关键取舍:
- Redisson中支持分布式可重入读写锁,这种锁允许同时有多个读锁和一个写锁对同一个资源进行加锁。
易错提醒:
- 关于Redisson实现分布式锁可以查看: 为了避免锁超时,Redisson中引入了看门狗的机制,他可以帮助我们在Redisson实例被关闭前,不断的延长锁的有效期。
加分表达:
- 在使用SETNX实现的分布式锁中,因为存在锁无法续期导致并发冲突的问题,所以在真实的生产环境中用的并不是很多,其实,真正在使用Redis时,用的比较多的是基于Redisson实现分布式锁。
- 默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改 Config.lockWatchdogTimeout 来另行指定。
追问准备:
- 围绕「Redisson」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「Redis」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「个可重入的分布式锁」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
在使用SETNX实现的分布式锁中,因为存在锁无法续期导致并发冲突的问题,所以在真实的生产环境中用的并不是很多,其实,真正在使用Redis时,用的比较多的是基于Redisson实现分布式锁。
> Redisson是一个基于Redis的Java客户端,它提供了丰富的功能,包括分布式锁的支持。 https://redisson.org/ > > 关于Redisson实现分布式锁可以查看:https://github.com/redisson/redisson/wiki/8.-Distributed-locks-and-synchronizers
为了避免锁超时,Redisson中引入了看门狗的机制,他可以帮助我们在Redisson实例被关闭前,不断的延长锁的有效期。
> 默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
可重入锁
基于Redisson可以非常简单的就获取一个可重入的分布式锁。基本步骤如下:
引入依赖:
java
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>最新版</version>
</dependency>定义一个Redisson客户端:
java
/**
* @author Hollis
*/
@Configuration
public class RedissonConfig {
@Bean(destroyMethod="shutdown")
public RedissonClient redisson() throws IOException {
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
return redisson;
}
}接下来,在想要使用分布式锁的地方做如下调用即可:
java
@Service
public class LockTestService{
@Autowired
RedissonClient redisson;
public void testLock(){
RLock lock = redisson.getLock("myLock");
try {
lock.lock();
// 执行需要加锁的代码
} finally {
lock.unlock();
}
}
}当然,也可以设置超时时间:
java
// 设置锁的超时时间为30秒
lock.lock(30, TimeUnit.SECONDS);
try {
// 执行需要保护的代码
} finally {
lock.unlock();
}以上方式,实现的是一个可重入的分布式锁,也就是说,获取到锁的线程可以再次尝试获取锁,并且这个锁也只能被这个线程解锁。
除了可重入锁以外,Redisson还支持公平锁(FairLock)以及联锁(MultiLock)的使用。
公平锁:
java
RLock fairLock = redisson.getFairLock("anyLock");
fairLock.lock();联锁:
java
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");
RedissonMultiLock lock = new RedissonMultiLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 所有的锁都上锁成功才算成功。
lock.lock();
...
lock.unlock();RedLock
为了解决Redis单点问题,引入了红锁的算法,Redisson中支持红锁的使用。示例在上面的文档中已经有了,这里就不再重复介绍了。
读写锁
Redisson中支持分布式可重入读写锁,这种锁允许同时有多个读锁和一个写锁对同一个资源进行加锁。
java
RReadWriteLock rwlock = redisson.getReadWriteLock("anyRWLock");
// 最常见的使用方法
rwlock.readLock().lock();
// 或
rwlock.writeLock().lock();