前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Redis实现分布式锁

Redis实现分布式锁

作者头像
zeekling
发布于 2022-08-26 11:58:45
发布于 2022-08-26 11:58:45
30501
代码可运行
举报
运行总次数:1
代码可运行

Redis被经常用来实现分布式锁,本文主要讲述redis如何实现一个分布式锁的demo。

获取锁

redis分布式锁的实现主要是通过redis的set命令实现:

代码语言:javascript
代码运行次数:0
运行
复制
SET key value nx PX milliseconds
  • nx : 当key存在的时候才将set对应的key,value写入到redis数据库里面。如果设置成功之后,就返回OK,已经存在就返回nil,当前set命令也是一个原子操作,可以作为分布式锁。
  • px milliseconds: 为当前key设置过期时间,当时间过了之后会将当前key删除。主要是方式获取锁之后未正常释放,导致死锁,一直无法获取锁。超时时间需要合理设置,需要保证当前业务能够处理完。
代码语言:javascript
代码运行次数:0
运行
复制
private static final String LOCK_SUCCESS = "OK";

  private static final Long UNLOCK_SUCCESS = 1L;

  //
  private static final String UNLOCK_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

  private final JedisCluster cluster;

  private final long lockTimeout;

  private final String lockKey;

  public RedisDistributedLockImpl(JedisCluster cluster, String lockKey, long lockTimeout) {

    this.cluster = cluster;
    this.lockTimeout = lockTimeout;
    this.lockKey = lockKey;
  }

  @Override
  public String lock() {
    long end = System.currentTimeMillis() + lockTimeout;
    String requireToken = String.valueOf(System.currentTimeMillis());
    int expireTime = 300 * 1000;
    SetParams params = new SetParams().nx().px(expireTime);
    while (System.currentTimeMillis() < end) {
      try {
        String result = cluster.set(lockKey, requireToken, params);
        if (LOCK_SUCCESS.equals(result)) {
          System.out.println("lock success");
          return requireToken;
        }
        System.out.println("lock failed trying");
        Thread.sleep(100);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }
    return requireToken;
  }

释放锁

释放锁,主要是需要通过原子操作将锁对应的key删除,可以通过下面lua脚本删除。

代码语言:javascript
代码运行次数:0
运行
复制
if redis.call('get', KEYS[1]) == ARGV[1] then 
   return redis.call('del', KEYS[1]) 
else 
    return 0 
end

释放锁的详细代码:

代码语言:javascript
代码运行次数:0
运行
复制
@Override
  public boolean unlock(String identify) {
    if (identify == null || identify.trim().length() == 0) {
      return false;
    }
    Object obj = new Object();
    try {
      obj = cluster.eval(UNLOCK_SCRIPT, Collections.singletonList(lockKey), Collections.singletonList(identify));
      if (UNLOCK_SUCCESS.equals(obj)) {
        System.out.println("release lock success, requestToken:" + identify);
        return true;
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("release lock failed, requestToken:" + identify + ", result:" + obj);
    return false;
  }

测试分布式锁

使用下面代码模拟秒杀场景:

代码语言:javascript
代码运行次数:0
运行
复制
public class RedisDistributedLockTest {

  static int n = 500;

  public static void secKill() {
    System.out.println("商品数量:" + --n);
  }

  public static void main(String[] args) {
    Runnable runnable = () -> {
      RedisDistributedLockImpl lock = null;
      String unLockIdentify = null;
      try {
        Set<HostAndPort> set = new HashSet<>();
        set.add(new HostAndPort("127.0.0.1", 30001));
        JedisPoolConfig config = new JedisPoolConfig();
        JedisCluster cluster = new JedisCluster(set, config);
        lock = new RedisDistributedLockImpl(cluster, "test1", 20000);
        unLockIdentify = lock.lock();
        System.out.println(Thread.currentThread().getName() + "正在运行");
        secKill();
      } finally {
        if (lock != null) {
          lock.unlock(unLockIdentify);
        }
      }
    };
    System.out.println("------------------开始--------------");
    for (int i = 0; i < 100; i++) {
      Thread t = new Thread(runnable);
      t.start();
    }
  }

}

执行结果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022.01.09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
redis系列:基于redis的分布式锁
这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁。会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁。
云枭
2018/08/28
5920
redis系列:基于redis的分布式锁
分布式锁用 Redis 好,还是 ZooKeeper 好?
提到锁大家肯定有了解,像 Synchronized、ReentrantLock,在单进程情况下,多个线程访问同一资源,可以用它们来保证线程的安全性。
用户2323866
2021/06/17
9580
Redis分布式锁正确打开方式
Tech 导读 本文主要从以下几个方面介绍Redis分布式锁:1、为什么要有分布式锁?2、分布式锁特性(五大特性 非常重要) 3、分布式锁特性2之不会发生死锁 4、分布式锁特性3:解铃还须系铃人 5.分布式锁特性4之可重入性 6、如何解决过期时间确定和业务执行时长不确定性的问题:看门狗机制
京东技术
2023/08/25
2180
Redis分布式锁正确打开方式
Redis(3)——分布式锁深入探究
如果 把一台服务器比作一个房子,那么 线程就好比里面的住户,当他们想要共同访问一个共享资源,例如厕所的时候,如果厕所门上没有锁...更甚者厕所没装门...这是会出原则性的问题的..
乔戈里
2020/03/13
5360
分布式锁用Redis好?还是Zookeeper好?
不过目前互联网项目越来越多的项目采用集群部署,也就是分布式情况,这两种锁就有些不够用了。
架构师修行之路
2020/12/31
1.2K0
分布式锁用Redis好?还是Zookeeper好?
redis 分布式锁的 5个坑,真是又大又深
最近项目上线的频率颇高,连着几天加班熬夜,身体有点吃不消精神也有些萎靡,无奈业务方催的紧,工期就在眼前只能硬着头皮上了。脑子浑浑噩噩的时候,写的就不能叫代码,可以直接叫做Bug。我就熬夜写了一个bug被骂惨了。
程序员小富
2020/04/22
2.3K0
SpringBoot系列之基于Jedis实现分布式锁
在单机环境,我们使用最多的是juc包里的单机锁,但是随着微服务分布式项目的普及,juc里的锁是不能控制分布锁环境的线程安全的,因为单机锁只能控制同个进程里的线程安全,不能控制多节点的线程安全,所以就需要使用分布式锁
SmileNicky
2023/12/13
1.5K0
SpringBoot系列之基于Jedis实现分布式锁
Redis从入门到放弃(10):分布式锁
在分布式系统中,实现对共享资源的安全访问是一个关键问题。Redis作为一种高性能的内存数据库,提供了多种方式来实现分布式锁,以解决多个节点之间对共享资源的并发访问问题。
夕阳也是醉了
2023/10/16
4010
Redis从入门到放弃(10):分布式锁
Redis 分布式锁(14)
在分布式系统中,有些业务场景会用到分布式锁,实现分布式锁的方式有很多,本篇主要讲根据Redis如何来实现。
兜兜毛毛
2021/05/18
5390
Redis 分布式锁(14)
如何优雅的使用Redis实现分布式锁
我们在多线程开发过程中,肯定没避免不了使用锁,jdk中也提供了大量的锁功能,但是我们为什么还要手动开发一个分布式锁呢,原因在于我们在传统项目中使用的锁是在同一个进程中的,他们能够相互访问到彼此的资源信息,但是在分布式中,每个项目都是跑在不同的进程中的,他们无法共享资源信息,所以就需要一个能够在不同进程之间进行“通信”的第三方来实现这个功能,那么redis其实就具备这种功能的。
AI码师
2020/11/19
9290
如何优雅的使用Redis实现分布式锁
redis学习(二十三)
  运行效果如下图所示。从图中可以看出,同一个资源在同一个时刻只能被一个线程获取,从而保证了库存数量N的递减是顺序的。
崔笑颜
2020/09/28
3880
jediscluster.set加锁_redislock
本人已实践的参考:https://blog.csdn.net/NullToSay/article/details/109813194
全栈程序员站长
2022/11/04
5570
Redis实现分布式锁的正确方式
封面为好友拍摄的照片,想查看更多微信公众号搜索:JavaBoy王皓或csdn博客搜索:TenaciousD
胖虎
2019/06/26
8870
Redis实现分布式锁的正确方式
使用Redis单实例实现分布式锁
在同一个jvm进程中时,可以使用JUC提供的一些锁来解决多个线程竞争同一个共享资源时候的线程安全问题,但是当多个不同机器上的不同jvm进程共同竞争同一个共享资源时候,juc包的锁就无能无力了,这时候就需要分布式锁了。常见的有使用zk的最小版本,redis的set函数,数据库锁来实现,本节我们谈谈Redis单实例情况下使用set函数来实现分布式锁。
加多
2018/09/06
5480
如何优雅的实现分布式锁?(文末赠书)
随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的JavaAPI并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题!
范蠡
2020/06/15
5280
redis命令和lua实现分布式锁
因为这个命令的性质,多个线程竞争时只有一个线程能修改key的值。利用这一点可以实现锁的互斥功能。
HUC思梦
2020/09/03
1.6K0
分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三...
分布式锁在分布式应用中应用广泛,想要搞懂一个新事物首先得了解它的由来,这样才能更加的理解甚至可以举一反三。
爱明依
2022/04/01
2490
redis实现分布式锁的原理_Redis作为分布式锁原理
现在面试,一般都会聊聊分布式系统这块的东西。通常面试官都会从服务框架(Spring Cloud、Dubbo)聊起,一路聊到分布式事务、分布式锁、ZooKeeper等知识。
全栈程序员站长
2022/11/17
1.1K0
redis实现分布式锁的原理_Redis作为分布式锁原理
分布式锁—-数据库和redis实现分布式锁
在博客“zookeeper实现分布式锁的两种方式”中介绍了分布式锁的使用场景,以及如何用zookeeper分别实现简单和高性能的分布式锁,这里就不再重复介绍分布式锁的场景,今天主要给大家带来另外两种实现分布式锁的方式–数据库、redis
全栈程序员站长
2022/07/04
5870
分布式锁—-数据库和redis实现分布式锁
Redis分布式锁的正确实现方式
数据库乐观锁 基于Redis的分布式锁 基于Zookeeper的分布式锁 本文介绍的是基于Redis的分布式锁;
stys35
2020/04/02
1.1K0
相关推荐
redis系列:基于redis的分布式锁
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档