redis的分布式锁框架redisson之体验分布式锁

使用

1、引入依赖:

<!--以后使用redis作为所有分布式锁,分布式对象等功能框架-->
<!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.12.0</version>
</dependency>

2、程序化配置方法

@Configuration
public class MyRedisConfig {

    @Bean(destroyMethod="shutdown")
    public RedissonClient redisson() throws IOException {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("li199852");
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

以后操作都是使用redissonClient操作:

@Autowired
RedissonClient redissonClient;

4、可重入锁(Reentrant Lock)

他的使用和java的Lack锁差不多:

@GetMapping("/hello")
@ResponseBody
public String hello(){
    //1.获取一把锁,只要锁的名字一样,就是同一把锁
    RLock lock = redisson.getLock("my-lock");
    //2.加锁
    lock.lock();//原理是阻塞式等待,默认加的锁都是30s的时间
    /*
    问题:lock.lock(10, TimeUnit.SECONDS)锁到期之后,不会自动续期。
        1、如果我们传递了锁的超时时间,就发送给redis执行脚本,进行占锁,默认超时就是我们指定的时间
        2、如果我们未指定锁的超时时间,就使用30*1000【lockWatchdogTimeout看门狗的默认时间】;
            只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】
            initernallockLeaseTime【看门狗时间】 / 3 ,也就是10秒调用一次重置时间方法

    */
    /*
    优点:
        1)、锁的自动续期,如果业务超长,运行期间自动给锁锁上新的30s。不用担心业务时间长,锁自动被删掉
        2)、加锁的业务自动运行完成,就不会给当前锁续期,即使不手动解锁,锁默认会在30s以后自动删除
    */
    try {
        System.out.println("我拿到了锁"+Thread.currentThread().getId());
            Thread.sleep(20000);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        //3.解锁,假设解锁代码没有运行,redisson会不会出现死锁:不会,锁默认会在30s以后自动删除
        System.out.println("我释放了锁"+Thread.currentThread().getId());
        lock.unlock();
    }
    return "hello";
}

 推荐使用:

  可以省掉续期的操作,如果业务30秒还执行不完,就要改造业务了;

lock.lock(30, TimeUnit.SECONDS);//锁到期之后,不会自动续期,需要手动解锁。

5、读写锁(ReadWriteLock)

    //保证一定能读到最新数据,修改期间,写锁是一个排他锁(互斥锁)。
    //读锁是一个共享锁写锁没释放读就必须等待
    /*
    先读 + 后读:相当于无锁,并发读,只会在redis中记录好,所有当前的读锁。他们都会同时加锁成功
    先写 + 后读:等待写锁释放
    先写 + 后写:阻塞方式
    先读 + 后写:有读锁。写也需要等待。
    只要有写的存在,都必须等待
     */
    @RequestMapping("/write")
    @ResponseBody
    public String writeString() {
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("readWriteLock");
        RLock wLock = readWriteLock.writeLock();
        String s = "";
        try {
            wLock.lock(20, TimeUnit.SECONDS);
            s = UUID.randomUUID().toString();
            Thread.sleep(10000);
            redisTemplate.opsForValue().set("s", s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            wLock.unlock();
        }
        return s;
    }

    @RequestMapping("/read")
    @ResponseBody
    public String readString() {
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("readWriteLock");
        RLock rLock = readWriteLock.readLock();
        String s = "";
        try {
            rLock.lock(20,TimeUnit.SECONDS);
            s =  redisTemplate.opsForValue().get("s");
        }finally {
            rLock.unlock();
        }

        return s;
    }

6、信号量(Semaphore)(还有一个可过期性信号量(PermitExpirableSemaphore))

    /**
* 信号量(Semaphore)
* 默认是获取的
* @return
*/
@RequestMapping("/goOneCar")
@ResponseBody
public String goOneCar(){
RSemaphore semaphore = redisson.getSemaphore("semaphore-Lock");
semaphore.release();//释放当前一个车位
return "出去一辆车";
}

@RequestMapping("/comeOneCar")
@ResponseBody
public String comeOneCar() throws InterruptedException {
RSemaphore semaphore = redisson.getSemaphore("semaphore-Lock");
// semaphore.acquire();//获取当前一个车位
semaphore.tryAcquire(10);//尝试获取当前十个车位,没有或不够就算了
return "进来一辆车";
}

7、闭锁(CountDownLatch)

    /**
     * 闭锁:CountDownLatch
     * 五个人都走出教室了在锁门,
     */
    //锁门
    @RequestMapping("/closeDoor")
    @ResponseBody
    public String closeDoor() throws InterruptedException {
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch-Lack");
        countDownLatch.trySetCount(5);
        countDownLatch.await();
        return "门锁了";
    }

    //出去
    @RequestMapping("/goOut")
    @ResponseBody
    public String goOut(Long id){
        RCountDownLatch countDownLatch = redisson.getCountDownLatch("countDownLatch-Lack");
        countDownLatch.countDown();
        return id+"出去了";
    }

其他可以参考redis官网,链接:https://github.com/redisson/redisson/wiki/8.-%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%E5%92%8C%E5%90%8C%E6%AD%A5%E5%99%A8

原文地址:https://www.cnblogs.com/lzghyh/p/13267880.html