redis之redisson分布式锁

转载
redis分布式锁
随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!

简单说就是保证在分布式环境下,解决这段代码同一时间只有一个线程访问,比如redis分布式锁防止分布式环境下的缓存击穿

1.setnx key(lock) value(uuid) + expire second (伪代码) 设置key(只有在 key 不存在时才能设置 key 的值)和过期时间
2.获取锁(能设置key值 即意味着拿到了锁) 如获取到了
3.查数据库 放入缓存
4.删除自己uuid的锁 return数据
5.没获取到锁的情况(没能设置key值)
6.线程休眠后自旋

另外这是不完善的,实际情况要加上lua脚本实现原子性 详情请看B站的尚硅谷redis视频课件

更方便的操作引入redisson实现分布式锁

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

配置类

@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config(); //redis://127.0.0.1:7181 //可以用"rediss://"来启用 SSL 连接
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        RedissonClient redisson = Redisson.create(config);
        return redisson;
    }
}

实现方法

    @RequestMapping("/hello7")
    @ResponseBody
    public int hello7(String username) throws Exception {

        //获取锁 只要锁的名字一样 就是一把锁
        RLock lock = redissonClient.getLock("123");

        //加锁 别的线程无限的堵塞性等待 二选一
        lock.lock();//锁的默认时间是30s后自动删除  业务时间长 redisson会对锁自动续期 不用指定时间
        lock.lock(1000, TimeUnit.MILLISECONDS); //传入指定时间 那么到期后不会自动续期
        try {

            System.out.println("加锁成功,执行业务....." + Thread.currentThread().getId());

            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //解锁  假设业务执行中断电 解锁代码没有运行 redisson也会自动释放锁
            lock.unlock();
        }

        return 1;
    }

读写锁

    /**
     * 读锁 一个共享锁
     * @return
     *
     * 读+读 相当于无锁
     * 写+读 写完才能读
     * 写+写 堵塞方式
     * 读+写 读完才能写 
     *
     * 只要有写的存在,都必须等待
     */
    @RequestMapping("/hello8")
    @ResponseBody
    public String hello8() {
        RReadWriteLock lock = redissonClient.getReadWriteLock("abc");
        RLock rLock = lock.readLock();

        try {
            rLock.lock();
            System.out.println("执行读业务代码");
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();
        }
        return "1";

    }

    /**
     * 写锁 一个排它锁
     * @return
     */
    @RequestMapping("/hello9")
    @ResponseBody
    public String hello9() {
        RReadWriteLock lock = redissonClient.getReadWriteLock("abc");
        RLock rLock = lock.writeLock();

        try {
            rLock.lock();
            System.out.println("执行写业务代码");
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            rLock.unlock();
        }

        return "1";
    }

信号量 停车例子
闭锁 锁门例子

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值