Redisson 分布式锁原理分析
示例程序
示例程序:
public class RedissonTest {
public static void main(String[] args) {
Config config = new Config();
config.useSingleServer()
.setPassword("123456")
.setAddress("redis://127.0.0.1:6379");
RedissonClient redisson = Redisson.create(config);
// RLock对象
RLock lock = redisson.getLock("MY_KEY");
ExecutorService pool = Executors.newFixedThreadPool(5);
IntStream.range(1, 5).forEach(item -> {
pool.execute(() -> {
try {
if (lock.tryLock(2000, TimeUnit.MILLISECONDS)) {
System.out.println(Thread.currentThread().getName() + "get Lock!!");
if (lock.tryLock(2000, TimeUnit.MILLISECONDS)) {
System.out.println(Thread.currentThread().getName() + "get Lock!!");
Thread.sleep(300000);
lock.unlock();
}
Thread.sleep(500000);
lock.unlock();
}
} catch (Exception e) {
System.out.println("error!!");
}
});
});
}
}
运行结果:
redis中的值:
原理
分布式锁实现加锁解锁都需要使用lua脚本。
利用Redis的Hash结构实现可重入。
Hash结构存值如下:
key | field | value |
---|
- key:就是分布式锁的key
- field:用于存储一个能够表示一个线程的唯一标识(Redisson使用的UUID)
- value:表示当前锁被同一个线程加锁的次数(可重入的实现方式)
下面以key为MY_KEY,field线程唯一标识为:WWSSWWWKKII99I为例,总结下加锁解锁流程:
加锁流程
加锁流程:
加锁之后,hash结构为
key | field | value |
---|---|---|
MY_KEY | WWSSWWWKKII99I | 1 |
实际的存储示例:
一个线程获取了一次:
一个线程获取了两次(可重入):
解锁流程
解锁流程:
假设当前锁的hash结构是
key | field | value |
---|---|---|
MY_KEY | WWSSWWWKKII99I | 2 |
这代表分布式锁 MY_KEY 被线程标识为 WWSSWWWKKII99I 的线程获取了两次
需要注意,整个加锁解锁的命令全都需要使用lua脚本。这样能保证操作的原子性。