Redisson基本用法


前言

Redisson是Redis官方推荐的Java版的Redis客户端。它提供的功能非常多,也非常强大,本文我们仅关注分布式锁的实现,更多请参考,官方文档


一、环境搭建

导入依赖

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

开启配置

@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer().setAddress("redis://192.168.170.130:6379");
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

二、可重入锁

默认,非公平锁

  • 锁的自动续期:如果业务运行时间超长,运行期间会自动给锁上新的30s,不用担心业务实际长,锁自动被删掉。
  • 加锁的业务只要完成,就不会给当前锁续期,即使不手动解锁,也会在30s后自动删除锁。
public Map<String, List<Catalog2Vo>> getCatalogJsonDbWithRedisson() {
        Map<String, List<Catalog2Vo>> categoryMap=null;
        //获得锁,名字为CatalogJson-Lock
        RLock lock = redissonClient.getLock("CatalogJson-Lock");
        //上锁,阻塞式等待,默认加的锁都是30s
        lock.lock();
        try {
            Thread.sleep(30000);
            //业务逻辑
            categoryMap = getCategoryMap();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
        	//解锁
            lock.unlock();
            return categoryMap;
        }
    }

lock.lock() 和 lock.lock(10, TimeUnit.SECONDS)区别

  • 如果我们指定了超时时间,就会发送给redis执行脚本,超过这个时间后锁便自动解开了。不会自动续期,无需调用unlock方法手动解锁,如果要手动解锁一定要确保业务执行时间小于锁的失效时间
  • 如果没有指定超时时间,就会使用30*1000(看门口的默认时间30s也可以通过修改Config.lockWatchdogTimeout来另行指定)。超过了1/3的看门狗时间(默认为10s,也就是还剩20s时就会重新续成30s),就会自动续期。
    在这里插入图片描述

tryLock

有最大等待时间,抢不到锁,不会一直傻傻的等待。

// 尝试加锁,最多等待100秒,上锁以后10秒自动解锁
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (res) {
   try {
     ...
   } finally {
       lock.unlock();
   }
}

读写锁(ReadWriteLock)

写锁会阻塞读锁,但是读锁不会阻塞读锁,但读锁会阻塞写锁

总之含有写的过程都会被阻塞,只有读读不会被阻塞

上锁时在redis的状态
在这里插入图片描述

@GetMapping("/read")
    @ResponseBody
    public String read() {
        RReadWriteLock lock = redissonClient.getReadWriteLock("ReadWrite-Lock");
        RLock rLock = lock.readLock();
        String s = "";
        try {
            rLock.lock();
            System.out.println("读锁加锁"+Thread.currentThread().getId());
            Thread.sleep(5000);
            s= redisTemplate.opsForValue().get("lock-value");
        }finally {
            rLock.unlock();
            return "读取完成:"+s;
        }
    }

    @GetMapping("/write")
    @ResponseBody
    public String write() {
        RReadWriteLock lock = redissonClient.getReadWriteLock("ReadWrite-Lock");
        RLock wLock = lock.writeLock();
        String s = UUID.randomUUID().toString();
        try {
            wLock.lock();
            System.out.println("写锁加锁"+Thread.currentThread().getId());
            Thread.sleep(10000);
            redisTemplate.opsForValue().set("lock-value",s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            wLock.unlock();
            return "写入完成:"+s;
        }
    }

信号量(Semaphore)

信号量为存储在redis中的一个数字,当这个数字大于0时,即可以调用acquire()方法增加数量,也可以调用release()方法减少数量,但是当调用release()之后小于0的话方法就会阻塞,直到数字大于0

@GetMapping("/park")
@ResponseBody
public String park() {
    RSemaphore park = redissonClient.getSemaphore("park");
    try {
        park.acquire(2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "停进2";
}

@GetMapping("/go")
@ResponseBody
public String go() {
    RSemaphore park = redissonClient.getSemaphore("park");
    park.release(2);
    return "开走2";
}

闭锁(CountDownLatch)

可以理解为门栓,使用若干个门栓将当前方法阻塞,只有当全部门栓都被放开时,当前方法才能继续执行。

以下代码只有offLatch()被调用5次后 setLatch()才能继续执行

@GetMapping("/setLatch")
    @ResponseBody
    public String setLatch() {
        RCountDownLatch latch = redissonClient.getCountDownLatch("CountDownLatch");
        try {
            latch.trySetCount(5);
            latch.await();//等待闭锁都完成
            //业务代码...
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "门栓被放开";
    }

    @GetMapping("/offLatch")
    @ResponseBody
    public String offLatch() {
        RCountDownLatch latch = redissonClient.getCountDownLatch("CountDownLatch");
        latch.countDown();
        return "门栓被放开1";
    }

闭锁在redis的存储状态
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值