redis分布式锁详解(优化redis分布式锁的过程及Redisson使用)

redis分布式锁详解(优化redis分布式锁的过程及Redisson使用)

1. redis在实际的应用中,不仅可以用来缓存数据,在分布式应用开发中,经常被用来当作分布式锁的使用,为什么要用到分布式锁呢?

在分布式的开发中,以电商库存的更新功能进行讲解,在实际的应用中相同功能的消费者是有多个的,假如多个消费者同一时刻要去消费一条数据,假如业务逻辑处理逻辑是查询出redis中的商品库存,而如果第一个进来的消费的消费者获取到库存了,还没进行减库存操作,相对晚来的消费者就获取了商品的库存,这样就导致数据会出错,导致消费的数据变多了。

例如:消费者A和消费者B分别去消费生产者C1和生产者C2的数据,而生产者都是使用同一个redis的数据库的,如果生产者C1接收到消费者A的消息后,先进行查询库存,然后当要进行减库存的时候,因为生产者C2接收到消费者B的消息后,也去查询库存,而因为生产者C1还没有进行库存的更新,导致生产者C2获取到的库存数是脏数据,而不是生产者C1更新后的数据,导致业务出错。
在这里插入图片描述
如果不是分布式的应用,可以使用synchronized进行防止库存更新的问题的产生,但是synchronized只是基于JVM层面的,如果在不同的JVM中,就不能实现这样的功能。


   @GetMapping("getInt0")
    public String test() {
   
        synchronized (this) {
   
            //获取当前商品的数量
            int productNum = Integer.parseInt(stringRedisTemplate.opsForValue().get("product"));
            //然后对商品进行出库操作,即进行减1
            /*
             * a业务逻辑
             *
             * */
            if (productNum > 0) {
   
                stringRedisTemplate.opsForValue().set("product", String.valueOf(productNum - 1));
                int productNumNow = productNum - 1;
            } else {
   
                return "product=0";
            }
            int productNumNow = productNum - 1;
            return "success=" + productNumNow;
        }
    }

2.如何使用redis的功能进行实现分布式锁

2.1 redis分布式锁思想

如果对redis熟悉的话,我们能够想到redis中具有setnx的命令,该命令的功能宇set功能类似,但是setnx的命令在进行存数据前,会检查redis中是否已经存在相同的key,如存在的话就返回false,反之则返回true,因此我们可以使用该命令的功能,设计一个分布式锁。

2.1.1设计思想:
  1. 在请求相同功能的接口时,使用redis的setnx命令,如果使用setnx命令后返回的是为true,说明此时没有其他的调用这个接口,就相当于获取到锁了,然后就可以继续执行接下来的业务逻辑了。当执行完业务逻辑后,在返回数据前,就把key删除了,然后其他的请求就能获取到锁了。
  2. 如果使用setnx命令,返回的是false,说明此时有其他的消费者正在调用这个接口,因此需要等待其他消费者顺利消费完成后,才能获取到分布式的锁。
2.1.2 根据上面的设计思想进行代码实现
代码片段【1】
  @GetMapping("getInt1")
    public String fubushisuo(){
   
        //setIfAbsent的指令功能和redis命令中的setNx功能一样,如果redis中已经存在相同的key,则返回false
        String lockkey = "yigehaimeirumengdechengxuyuan";
        String lockvalue = "yigehaimeirumengdechengxuyuan";
        boolean opsForSet = stringRedisTemplate.opsForValue().setIfAbsent(lockkey,lockvalue);
        //如果能够成功的设置lockkey,这说明当前获取到分布式锁
        if (!opsForSet){
   
            return "false";
        }
        //获取当前商品的数量
        int productNum = Integer.parseInt(stringRedisTemplate.opsForValue().get("product"));
        
  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值