> 文档中心 > Redisson分布式锁使用

Redisson分布式锁使用

目录

    • 加锁问题
    • 使用redisson分布式锁
      • 1、配置
      • 2、正常加锁
      • 3、读写锁
      • 4、闭锁
      • 5、信号量

不加锁问题

例如:我们在调用操作redis接口,获取key减去1在set进去。这样的操作,再遇到高并发时,大家get的数据都一样,都减去1,再set进去,这样数据肯定是错的。

@Testvoid contextLoads() {Long num = (Long) redisUtil.get("num");num = num - 1;redisUtil.set("num",num);}

使用synchronized同步锁或者redis加锁都会有很多问题

使用redisson分布式锁

在这里插入图片描述

1、配置

1、引入依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.16.1</version></dependency>

2、配置

@Configurationpublic class RedissonConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private String port;@Value("${spring.redis.password}")private String password;@Beanpublic RedissonClient redissonClient() {Config config = new Config();// config.useClusterServers().addNodeAddress("redis://" + host + ":" + port); // 分片集群方式SingleServerConfig server = config.useSingleServer();config.setLockWatchdogTimeout(5 * 1000L);server.setAddress("redis://" + host + ":" + port);server.setPassword(password);RedissonClient redissonClient = Redisson.create(config);return redissonClient;}}

2、正常加锁

@AutowiredRedisson redisson;RLock lock = redisson.getLock("lockKey"); //获取锁lock.lock(); //加锁,注射性等待。默认加的锁的时间是30s。// 1)、锁自动续期,如果业务时间超长,运行期间自动给锁续上新的30s.// 2)、加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30s以后删除// 加锁以后10秒钟自动解锁// 无需调用unlock方法手动解锁// lock.lock(10, TimeUnit.SECONDS);// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁// boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);try {    // redis操作.} finally {    lock.unlock(); // 释放锁}

3、读写锁

写锁没完成,就读取不到数据。保证能读到最新数据。

@Testpublic void  write(){// 获取读写锁RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");RLock rLock = lock.writeLock();try {rLock.lock();  // 给写加锁,写没完成,读就读不出来redisUtil.set("num",1);}finally {// 释放锁rLock.unlock();}}@Testpublic void  read(){// 获取读写锁RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");RLock rLock = lock.readLock();rLock.lock();  // 加读锁,写锁没完成,就读不了try {redisUtil.get("num");}finally {// 释放锁rLock.unlock();}}

4、闭锁

调用次数为我们设置的次数后就锁住。

@Test // 闭锁,设置次数和锁public void lockDoor() throws InterruptedException {RCountDownLatch door = redisson.getCountDownLatch("door");door.trySetCount(5); // 5次后就锁住door.await();}@Test // 闭锁  调一次,次数就减1,等到上面设置的5次后,就锁住public void door() throws InterruptedException {RCountDownLatch door = redisson.getCountDownLatch("door");door.countDown();}

5、信号量

信号量占用与释放:如设置停车场有3个车位,每次占用一个信号,等到占用到了3个,就会等待(或者可以返回false),这时再释放一个信号量,才能占用得到。

@Testpublic void setparkCount()  {redisUtil.set("park",3); // 设置这个停车场有三个车位}@Test // 占用一个,如果3个都占用了,就锁住,一直等待public void park() throws InterruptedException {RSemaphore park = redisson.getSemaphore("park");park.acquire(); //占用一个信号,获取一个值(如:占用一个车位),堵塞性等待// 或者// boolean b = park.tryAcquire();// 占用一个信号,如果车位位,返回false}@Test // 释放一个public void go() throws InterruptedException {RSemaphore park = redisson.getSemaphore("park");park.release(); //释放一个信号(如: 释放一个车位)}