其他分享
首页 > 其他分享> > 项目中分布式锁的实现方式(技术篇)

项目中分布式锁的实现方式(技术篇)

作者:互联网

前提:使用redis实现分布式锁

1.在pom文件中导入java对redis分布式锁的支持依赖:

<!--        实现分布式锁依赖-->
        <!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.16.8</version>
        </dependency>

2.编写配置类

@Configuration
public class MyRedissonConfig {
    /**
     * destroyMethod定义销毁方法
     * @return
     */
    @Bean(destroyMethod = "shutdown",value = "redisson")
    RedissonClient getRedissonClient(){
        //创建配置
        Config config = new Config();
        //这里的redis地址是你自己的
        config.useSingleServer().setAddress("redis://158.72.233.198:6379");
        //根据config创建出实例
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;

    }
}

3.分布式锁的原理

        redis分布式锁与JUC的Lock锁的实现基本一致,lock()方法加锁,unlock()方法解锁
        1.可重入锁(Reentrant Lock):如果在锁的内部有嵌套锁,并且是同一把锁的话,内部可以直接执行,即内部可以使用外部锁  

@GetMapping("hello")
    @ResponseBody
    public String hello() {
        //使用分布式锁,通过锁客户端->取得一把锁,并定义锁名字,只要锁的名字一致就是同一把锁
        //RLock继承与lock
        RLock lock = redisson.getLock("my-lock");
        //加锁
        //如果我们传递了锁的超时时间,就发送redis脚本,进行占锁,默认超时时间就是我们指定的时间
        //如果我们没有传递锁超时时间,就使用看门狗的30*1000,后端会通过异步编排的定时器机制,发现线程还在运行,并且在10s,调用方法重新延时为30s
        lock.lock();//这个加锁是阻塞式等待
        //锁的自动续期,如果业务超长,每当运行到默认时间的/3,自动给锁续上30秒(看门狗机制)
        try {
//            取得线程id
            System.out.println("加锁成功,执行业务...."+Thread.currentThread().getId());
            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //解锁,此处即使代码没有运行也会解锁,因为看门狗机制
            lock.unlock();
            System.out.println("解锁成功...."+Thread.currentThread().getId());
        }
        return "hello";
    }

        2.公平锁(Fair Lock):它保证当多个redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程

   @GetMapping("read")//读锁是共享锁
    @ResponseBody
    public String readValue(){
        //获取读写锁对象
        RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");
        //获取读锁
        RLock rLock = lock.readLock();
        String s = "";
        try {
            rLock.lock();//加锁
            s = stringRedisTemplate.opsForValue().get("writeValue");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();//解锁
        }
        return s;
    }

    @GetMapping("write")//写锁是排他锁
    @ResponseBody
    public String writeValue(){
        //获取读写锁对象
        RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");
        //改数据用写锁
        RLock rLock = lock.writeLock();
        String s = "";
        try {
            rLock.lock();//加锁
            s = UUID.randomUUID().toString().replaceAll("-","");
            Thread.sleep(30000);
            //将s放入到缓存中
            stringRedisTemplate.opsForValue().set("writeValue",s);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();//解锁
        }
        return s;
    }

4.信号量(Semaphore):基于redis的redisson的分布式信号量,类似于占车位

/**
     * 车库停车
     * 3车位
     */
    @GetMapping("park")//停车方法
    @ResponseBody
    public String park() throws InterruptedException {
        //取得信号量对象
        RSemaphore park = redisson.getSemaphore("park");
        //park.acquire();//获取一个信号,获取一个值,占一个车位,阻塞式获取
        boolean b = park.tryAcquire();//尝试获取如果没有直接进行返回
        return "ok";
    }

    @GetMapping("go")//开车走方法
    @ResponseBody
    public String go(){
        //取得信号量对象
        RSemaphore park = redisson.getSemaphore("park");
        park.release();//释放车位
        return "ok";
    }

5.闭锁(CountDownLatch):基于redis的redisson的分布式闭锁,类似于放假锁门

/**
     * 放假,锁门
     * 需要五个班都走完,才能锁门
     */
    @GetMapping("lockDoor")
    @ResponseBody
    public String lockDoor() throws InterruptedException {
        //获取闭锁对象
        RCountDownLatch door = redisson.getCountDownLatch("door");
        //设置需要关闭的数量
        door.trySetCount(5);
        door.await();//等待闭锁都完成
        return "放假了";
    }
    @GetMapping("gogogo/{id}")
    @ResponseBody
    public String gogogo(@PathVariable("id")String id){
        //获取闭锁对象
        RCountDownLatch door = redisson.getCountDownLatch("door");
        door.countDown();//计数减一
        return id+"班人走完了...";
    }

标签:redisson,return,String,方式,项目,lock,park,加锁,分布式
来源: https://blog.csdn.net/qq_1757537040/article/details/122782123