我们先创建一个Maven工程,然后从一个简单Demo案例来入手。
Redis可重入锁Demo
创建一个maven工程,在pom中引入依赖,本次我们就采用Redisson 3.8.1版本:
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.8.1</version> </dependency>
如下Demo中Redis的环境采用三主三从的方式搭建一套Redis-Cluster集群环境(搭建Redis-Cluster集群的步骤这里省略,我们重点关注源码层面),Demo代码示例如下:
public class App {
public static void main(String[] args) throws Exception {
// 1.配置Redis-Cluster集群节点的ip和port
Config config = new Config();
// redis-cluster集群的ip和port
config.useClusterServers().addNodeAddress("redis://10.238.221.101:7001")
.addNodeAddress("redis://192.168.43.159:7002").addNodeAddress("redis://192.168.43.159:7003");
// 2.通过以上配置创建Redisson的客户端
RedissonClient redisson = Redisson.create(config);
// 3.测试Redisson可重入锁的加锁、释放锁等功能
testRedissonSimpleLock(redisson);
}
private static void testRedissonSimpleLock(RedissonClient redisson) throws InterruptedException {
// 1.获取key为"anyLock"的锁对象
RLock lock = redisson.getLock("anyLock");
// 2.1:加锁
lock.lock();
// 2.2:加锁时,设置尝试获取锁超时时间30s、锁超时自动释放的时间10s
// lock.tryLock(30, 10, TimeUnit.MILLISECONDS);
Thread.sleep(10 * 1000);
// 3.释放锁
lock.unlock();
}
}
Demo比较简单,就是我们平常开发高频用到的一些Api,包括加锁和释放锁,但是底层是如何实现加锁这一语义的呢?
1:客户端线程在底层是如何实现加锁的?
2:客户端线程是如何维持加锁的?
带着这些迷雾般的困惑,接下来的源码环节、我们好好的看一下。
1、找哪台机器加锁呢?
首先我们先看下它是怎么获取一个锁对象的,如下图:
RLock对象表示一个锁对象,这里表示我们要对key为anyLock加锁,先获取一个锁对象。
首先我们可以先猜下,既然是要加锁,具体体现到Redis底层命令上肯定就是最朴素的set key value的方式啊,我们先不管它里面的其他各种复杂机制,
第一个问题肯定就是要在Redis-Cluster集群中、那么多的master节点中选择一个master节点来加锁即执行命令
此时肯定会是在redisson.getLock方法中、针对"anyLock"这个key就选择好了要对哪个master节点上加锁,然后下一步的lock.lock直接