分布式锁_redis实现

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 分布式锁_redis实现

为什么引入分布式锁?

在微服务中, 例如一个订单系统需要调用不同的商品库, 商品库里的数据保持一致,那么在不同的微服务之间, 一次只能由一个请求来访问, 那么在对两个库上就要加一个东西来识别,有没有线程在访问这个共同的资源,这即使分布式锁的思想

●特性
在这里插入图片描述

实现分布式锁

方式 1:SETNX 命令

要实现分布式锁,必须要求 Redis 有互斥的能力。可以使用 SETNX 命令,
其含义是 SET IF NOT EXIST,即如果 key 不存在,才会设置它的值,否则什么
也不做。两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式

在这里插入图片描述

代码

    /*
      扣库存方法
      分布式锁1:
     */
    @RequestMapping(path = "/sub")
    public  String subStock(){
   
   
        //尝试向redis中设置一个键(锁),哪个线程设置成功,就获得锁, 设置成功返回true,失败则返回false
        String clientid = UUID.randomUUID().toString();
       try {
   
   
           boolean res =     redisTemplate.opsForValue().setIfAbsent("stock_lock",clientid,15, TimeUnit.SECONDS);
           if(!res){
   
   //获取锁失败
               return "fail";
           }
           //查询库存
           Integer count =     (Integer) redisTemplate.opsForValue().get("stock");
           if(count>0){
   
   
               count = count-1;
               redisTemplate.opsForValue().set("stock",count);
               return "success";
           }else{
   
   
               return "fail";
           }
       }finally {
   
   
             String id = (String)redisTemplate.opsForValue().get("stock_lock");
             if(id.equals(clientid)){
   
   
                 redisTemplate.delete("stock_lock");// 确保键最终是会被删除释放的
             }
       }
    }

这里由两个要点:

  1. 要给该代码添加finally,保证最后会释放锁,防止死锁; 例如程序报错,宕机
  2. 给redis的key添加失效时间, 防止该线程出错,或者该服务宕机之后, 造成持续持有锁__死锁, 使得其他线程无法操作
  3. 添加UUID,在finally要释放锁之前要判断, 保证是释放当前的锁

但是设置失效时间 10s,有可能业务执行时间大于 10s,那么锁会失效,导致其
他线程进入到减库存业务中,这时,第一个线程执行完成,会误删除第二个线程的
锁标志,导致其他线程进入.导致锁永久失效.

所以锁的失效时间一直是一个问题

所以就有了下面的方案

方式 2: 使用 redission

●依赖

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

●创建 Redisson 对象

    //创建 Redisson 对象
    @Bean
    public Redisson getRedisson() {
   
   
        Config config = new Config();
        config.useSingleServer().setAddress("redis://120.48.37.232:6379").se
        tDatabase(0);
        return (Redisson) Redisson.create(config);
    }

●使用 Redisson 实现加锁,释放锁.
在这里插入图片描述

此时就算程序运行时间超过了设置的时间,RLock锁也会添加时间,防止其他线程进入;
始终保证该程序运行完成,同时finally会保证程序不会造成死锁

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
18天前
|
NoSQL Java Redis
redis分布式锁
redis分布式锁
|
5天前
|
存储 NoSQL 算法
Redis (分布式锁)
Redis (分布式锁)
183 0
|
18天前
|
NoSQL Redis 微服务
分布式锁_redis实现
分布式锁_redis实现
|
18天前
|
NoSQL Java 关系型数据库
浅谈Redis实现分布式锁
浅谈Redis实现分布式锁
33 0
|
8月前
|
NoSQL Java 关系型数据库
Redis-分布式锁
分布式锁的基本原理和实现方式对比 分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行,这就是分布式锁的核心思路 在分布式情况下有多个JVM,所以就有多个锁监视器,所以就存在有多个线程拿到锁,他们就会产生不互斥的情况,这也是我们为什么要使用分布式锁的原因。而从图中我们也可以看到分布式锁的原理:让多个微服务共用一个锁监视器,这样就不会有多把锁同时存在的情况。 那么分布式锁他应该满足一些什么样的条件呢? 可见性:多个线程都能看到相同的结果,注意:这个地方说的
37 1
|
10月前
|
负载均衡 NoSQL Java
基于redis和shedlock实现分布式锁(超简单)
基于redis和shedlock实现分布式锁(超简单)
283 0
|
11月前
|
存储 NoSQL Redis
基于redis实现分布式锁(下)
基于redis实现分布式锁(下)
|
11月前
|
NoSQL 算法 Redis
Redis的分布式锁
Redis的分布式锁的基本实现和注意事项
54 0
|
运维 NoSQL 安全
被问烂的Redis分布式锁,你真的懂了? 下
被问烂的Redis分布式锁,你真的懂了? 下
|
NoSQL 安全 JavaScript
被问烂的Redis分布式锁,你真的懂了? 上
被问烂的Redis分布式锁,你真的懂了?上
被问烂的Redis分布式锁,你真的懂了? 上