分布式锁_redis实现

本文涉及的产品
可观测可视化 Grafana 版,10个用户账号 1个月
应用实时监控服务-应用监控,每月50GB免费额度
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 分布式锁_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
相关文章
|
2月前
|
NoSQL Java Redis
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
Redis分布式锁在高并发场景下是重要的技术手段,但其实现过程中常遇到五大深坑:**原子性问题**、**连接耗尽问题**、**锁过期问题**、**锁失效问题**以及**锁分段问题**。这些问题不仅影响系统的稳定性和性能,还可能导致数据不一致。尼恩在实际项目中总结了这些坑,并提供了详细的解决方案,包括使用Lua脚本保证原子性、设置合理的锁过期时间和使用看门狗机制、以及通过锁分段提升性能。这些经验和技巧对面试和实际开发都有很大帮助,值得深入学习和实践。
太惨痛: Redis 分布式锁 5个大坑,又大又深, 如何才能 避开 ?
|
4月前
|
NoSQL Redis
基于Redis的高可用分布式锁——RedLock
这篇文章介绍了基于Redis的高可用分布式锁RedLock的概念、工作流程、获取和释放锁的方法,以及RedLock相比单机锁在高可用性上的优势,同时指出了其在某些特殊场景下的不足,并提到了ZooKeeper作为另一种实现分布式锁的方案。
125 2
基于Redis的高可用分布式锁——RedLock
|
4月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
5月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
27天前
|
NoSQL Redis
Redis分布式锁如何实现 ?
Redis分布式锁通过SETNX指令实现,确保仅在键不存在时设置值。此机制用于控制多个线程对共享资源的访问,避免并发冲突。然而,实际应用中需解决死锁、锁超时、归一化、可重入及阻塞等问题,以确保系统的稳定性和可靠性。解决方案包括设置锁超时、引入Watch Dog机制、使用ThreadLocal绑定加解锁操作、实现计数器支持可重入锁以及采用自旋锁思想处理阻塞请求。
54 16
|
2月前
|
缓存 NoSQL Java
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
64 3
大数据-50 Redis 分布式锁 乐观锁 Watch SETNX Lua Redisson分布式锁 Java实现分布式锁
|
5月前
|
NoSQL Java Redis
分布式锁实现原理问题之使用Redis的setNx命令来实现分布式锁问题如何解决
分布式锁实现原理问题之使用Redis的setNx命令来实现分布式锁问题如何解决
|
2月前
|
NoSQL Redis 数据库
计数器 分布式锁 redis实现
【10月更文挑战第5天】
51 1
|
2月前
|
NoSQL 算法 关系型数据库
Redis分布式锁
【10月更文挑战第1天】分布式锁用于在多进程环境中保护共享资源,防止并发冲突。通常借助外部系统如Redis或Zookeeper实现。通过`SETNX`命令加锁,并设置过期时间防止死锁。为避免误删他人锁,加锁时附带唯一标识,解锁前验证。面对锁提前过期的问题,可使用守护线程自动续期。在Redis集群中,需考虑主从同步延迟导致的锁丢失问题,Redlock算法可提高锁的可靠性。
83 4
|
2月前
|
缓存 NoSQL 算法
面试题:Redis如何实现分布式锁!
面试题:Redis如何实现分布式锁!