首页 > 数据库 >redis分布式锁实现

redis分布式锁实现

时间:2023-06-26 23:34:07浏览次数:41  
标签:intNum String 实现 lock opsForValue redis num redisTemplate 分布式

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

   //有死锁问题,设置锁的过期时间防止死锁
    public void incr() {
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "1111");	//setnx,只有key不存在才能设置成功
        if (lock) {
            String num = redisTemplate.opsForValue().get("num");
            Integer intNum = Integer.valueOf(num);
            intNum = intNum + 1;
            redisTemplate.opsForValue().set("num",intNum.toString());
            redisTemplate.delete("lock");
        }else {
            incr();
        }
public void incr() {
    //设置过期时间后出现了锁不住、删除别人锁的问题
    //保证加锁和设置锁时间原子性
    Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "1111",30, TimeUnit.SECONDS);
    if (lock) {
        String num = redisTemplate.opsForValue().get("num");
        Integer intNum = Integer.valueOf(num);
        intNum = intNum + 1;
        redisTemplate.opsForValue().set("num",intNum.toString());
        redisTemplate.delete("lock");
    }else {
        incr();
    }
    public void incr() {

        //给当前线程设置一个标识,在删除锁的时候,判断一下这把锁是否是自己的,锁不住问题没有解决
        String uuid = UUID.randomUUID().toString();
        //保证加锁和设置锁时间原子性
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 30, TimeUnit.SECONDS);
        if (lock) {
            String num = redisTemplate.opsForValue().get("num");
            Integer intNum = Integer.valueOf(num);
            intNum = intNum + 1;
            redisTemplate.opsForValue().set("num", intNum.toString());

            //使用lua表达式确保拿比删操作的原子性
            String luaString = "if redis.call('get',KEYS[1]) == ARGV[1] " +
                    "then " +
                    "return redis.call('del',KEYS[1]) " +
                    "else " +
                    "   return 0 " +
                    "end";
            redisTemplate.execute(new DefaultRedisScript<Long>(luaString, Long.class), Arrays.asList("lock"), uuid);
/*            String redisUuid = redisTemplate.opsForValue().get("lock");
            if(uuid.equals(redisUuid)){
                redisTemplate.delete("lock");
            }*/
        } else {
            incr();
        }
    }

使用Redission解决锁不住的问题

如果没有添加过期时间,默认锁时间是30s,且每到20s,会再次续期成30s,直到释放锁,或者是出现宕机 ,出现异常, 为止

分布式锁面试回答思路

1、介绍单体锁
2、引入分布式锁 手写分布式锁 遇见的问题 解决这些问题
3、我们工作中使用的是redisson,引出看门狗这个名词,总结源码
4、我们在项目中如何使用

Redission源码

1、抢锁的时候,以看门狗时间作为锁失效时间,每隔 30s (看门狗时间)/3 = 10s 再续约成30s
2、如果你设置了时间,就以你设置的时间作为锁失效时间,还不会续期

标签:intNum,String,实现,lock,opsForValue,redis,num,redisTemplate,分布式
From: https://www.cnblogs.com/DuX1ao/p/17507440.html

相关文章

  • JQ 用最少代码实现瀑布流布局
    <!DOCTYPEhtml><htmllang="zh-cn"><head><metacharset="UTF-8"><title></title><style>html{_background:url(about:blank);}body{background-color:#fff;color:#333;overflow-x:hidden;}body,......
  • 分布式事务、CAP理论、BASE理论
    分布式事务、CAP理论、BASE理论什么是分布式事务?首先理解什么是本地事务?平常我们在程序中控制事务是利用数据库本身的事务特性来实现的,比如spring中的@Transactional注解,因此叫数据库事务。由于应用主要靠关系数据库来控制事务,此数据库只属于该应用,所以基于本应用自己的关......
  • 自己动手实现rpc框架(一) 实现点对点的rpc通信
    自己动手实现rpc框架(一)实现点对点的rpc通信1.什么是rpc?RPC是远过程调用(RemoteProcedureCall)的缩写形式,其区别于一个程序内部基本的过程调用(或者叫函数/方法调用)。随着应用程序变得越来越复杂,在单个机器上中仅通过一个进程来运行整个应用程序的方式已经难以满足现实......
  • 【Vue】Vue3+Vite 实现 SVG 组件自动加载 icons 目录下所有文件
    1.安装依赖插件vite-plugin-svg-iconsvite-plugin-svg-icons用于生成svg雪碧图。特点:1.预加载在项目运行时就生成所有图标,只需操作一次dom2.高性能内置缓存,仅当文件被修改时才会重新生成vite-plugin-svg-icons官方文档pnpmaddvite-plugin-svg-icons2.安装......
  • redis初见
    redis介绍redis下载:1、官网:https://redis.io/-目前最稳定:6.x版本-最新版本:7.x2、中文网:http://redis.cn/download.html-上面最新只到5.x版本3、windows版本下载地址-redis官方不提供windows版本,但windows封装了一些安装包,使其可以安装在linux下......
  • 转载: redis中的bigkey问题
    reference:  https://www.modb.pro/db/459810 什么是bigkeybigkey就是rediskey/value体系中的大value问题。我们知道redis的底层数据存储结构中,有多种数据结构的实现。String:简单动态字符串List:双向链表、压缩列表 Hash:哈希表、压缩列表 SortedSet:跳表、压......
  • 记录--巧用 overflow-scroll 实现丝滑轮播图
    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助前言:近期我在项目中就接到了一个完成轮播图组件的需求。最开始我也像大家一样,直接选择使用了知名的开源项目"Swiper",但是后来发现它在移动端项目中某些测试环境下会白屏一段时间。无论如何调试都不能修复这个问......
  • IS200TRLYS1BGG,要使它能够在自控设备间实现通信,所以你需要一个工业级的通信协议
    IS200TRLYS1BGG,要使它能够在自控设备间实现通信,所以你需要一个工业级的通信协议IS200TRLYS1BGG,要使它能够在自控设备间实现通信,所以你需要一个工业级的通信协议 在工厂生产层使用工业以太网之前,必须了解它的七个要素。这里,我们以Profinet标准为例,为大家一一进行介绍。1.......
  • 基于Java+selenium+Chrome,实现截取html页面内容并保存为图片
    1、需求实现Java程序发送邮件,并将输入的多个页面转为pdf类型附件一同发送出去。而页面如何转为pdf呢?其中的一个方案就是先将html页面转为图片,再将图片合并为pdf。此文记录的是html=>png过程。2、开发主要依赖<!--html2image--><dependency><groupId>org.seleniumhq.se......
  • 基于docker部署redis
    Docker中部署redis一、在docker中拉去redis镜像dockerpullredis二、在本机给redis创建配置文件1.mkdir–p/root/docker/redis/conf2.上传redis自带的redis.conf到改目录下。注意:有可能xftp无法链接,可以先传到其他目录,在linux中移动到该目录3.编辑redis.conf配置文件3.1.把bind......