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

利用redis实现 分布式锁

时间:2023-05-16 19:12:59浏览次数:37  
标签:return String redis 利用 call new lockKey 分布式

利用redis实现 分布式锁

 

 1.给需要添加锁的地方添加锁

    @GetMapping("/get")
    public String test(HttpServletRequest request) throws InterruptedException {

        System.out.println("begin to do");

        String requestId = request.getSession().getId();
        String lockName = "Lock_Common_Dict_test";
        System.out.println("requestId " + requestId);

        boolean flag = this.authorityStore.tryGetDistributedLock(new Memo.Builder(lockName).value(requestId).expireTime(-1).build());
        try{
            if(flag) {
                Integer testKeyNum = (Integer) this.authorityStore.get("testKey");
                System.out.println("testKey " + testKeyNum);
                Thread.sleep(10000);
                if (testKeyNum < 1) {
                    System.out.println("testKeyNum < 0> will return");
                    return "testKeyNum < 0 will return;";
                }

                int i = 2/0;

                --testKeyNum;
                System.out.println("complete testkey ++");

                this.authorityStore.save(new Memo.Builder("testKey").value(testKeyNum).expireTime(10000).build());

                return "success;";
            } else{
                return "can not call now";
            }
        }
        catch (Exception ex){
            logger.error("running error");
            ex.printStackTrace();
        }finally {
            this.authorityStore.releaseDistributedLock(lockName, requestId);
        }
        return "can not call now";
    }

 

  2.redis添加锁,释放锁

    @Override
    public boolean tryGetDistributedLock(Memo memo) {
        String script = "if redis.call('setNx',KEYS[1],ARGV[1]) then if redis.call('get',KEYS[1])==ARGV[1] then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end end";
        RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        boolean beginDog = false;
        int expireTime = memo.expireTime();

        if (expireTime == -1) {
            expireTime = RedisUtil.lockWatchdogTimeout;
            beginDog = true;
        }

        Object result = redisTemplate.execute(redisScript, new StringRedisSerializer(), new StringRedisSerializer(),
                Collections.singletonList(memo.key()), memo.value(), expireTime + "");
        boolean equals = SUCCESS.equals(result);
        if (equals && beginDog) {
            lockWatchdog.beginLockWatchdog(memo.key(), memo.value().toString());
        }
        return equals;
    }

    public boolean releaseDistributedLock(String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        Object result = redisTemplate.execute(redisScript, new StringRedisSerializer(), new StringRedisSerializer(),
                Collections.singletonList(lockKey), requestId);

        return SUCCESS.equals(result);
    }

  3.添加看门狗, 给未执行完的key延长时间

    //    watch dog
    public class LockWatchdog {

        private Timer TIMER = new Timer();

        /**
         * 开启一个看门狗
         *
         * @param lockKey
         * @return
         */
        public void beginLockWatchdog(String lockKey, String val) {
            renewExpiration(lockKey, val);
        }

        /**
         * 延长锁过期时间
         *
         * @param
         * @return
         */
        private void renewExpiration(String lockKey, String val) {
            TIMER.schedule(new TimerTask() {
                @Override
                public void run() {
                    try {
                        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('expire', KEYS[1], ARGV[2]) else return 0 end";
                        RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
                        Object result = redisTemplate.execute(redisScript, new StringRedisSerializer(), new StringRedisSerializer(),
                                Collections.singletonList(lockKey), val, String.valueOf(lockWatchdogTimeout));
                        if (Objects.equals(result, 1L)) {
                            renewExpiration(lockKey, val);
                        }
                    } catch (Exception e) {
                        logger.error("redis锁延长失败!", e);
                    }
                }
            }, lockWatchdogTimeout * 1000 / 3L);
        }

    }

 

标签:return,String,redis,利用,call,new,lockKey,分布式
From: https://www.cnblogs.com/goblinn/p/17406532.html

相关文章

  • APP自动化-异常截图-利用内存空间(list)
    先在package目录下建立一个文件,如:什么情况下可以操作内存空间.py里面建立一个列表:list1=[]因为conftest可以在很多层级都存在比如:我们在testcase目录下的conftest-1文件中没有pytest异常截图的那段代码(最下面注释掉的部分)1#!/usr/bin/envpython2#-*-coding:utf-8......
  • rocket mq实现分布式事务
    使用rocketmq实现分布式事务发送半消息->执行本地事务->回查本地事务执行状态->第二个服务消费事务消息 1.参照下面链接去安装rocketmqhttps://blog.csdn.net/weixin_43464076/article/details/127766159rocketmq启动命令:startmqnamesrv.cmdst......
  • redis学习2通用命令--黑马
    key通用操作基本操作delkeyexistskeytypekey扩展操作为指定key设置有效期expirekeysecondspexpirekeymillisecondsexpireatkeytimestamppexpireatkeymilliseconds-timestamp获取key的有效时间(剩余时间)ttlkey(返回-2代表key已消失,返回-1表示存在key,返回其......
  • 外汇天眼:炒外汇赚钱很难?利用好市场波动,菜鸟也可以赚钱!
    在股市中,不管是在上涨行情还是下跌行情,总会有投资者遭受亏损。即使在表面上看起来趋势明显,许多人仍然难以从中获利。这是因为趋势并非像我们想象的那样容易利用。在实际交易中,趋势并非总是那么有价值,所以需要我们更深入地理解和应用趋势。在交易中,我们需要学会辨识和利用趋势,但同时......
  • 分布式session的解决方案
    一、背景一个服务要部署在多台服务器上时,用户信息记录在session中。如果用户小白的登录请求打到服务器A上,这时服务器A会记录session。之后用户小白的下单请求打到服务器B上,由于服务器B没有保存用户A的session,所以用户小白需要再次登录后,才能下单。为了解决用户重复登录的问题,提......
  • 利用matlab和simulink搭建的纯跟踪控制器用于单移线轨迹跟踪,效果如图。
    利用matlab和simulink搭建的纯跟踪控制器用于单移线轨迹跟踪,效果如图。版本各为2018b和2019购买内容包含:1、simulink模型2、纯跟踪算法的纯matlab代码,便于理解纯跟踪算法以及如何从代码到simulink模型的搭建。3、帮助文档ID:2129675635054581......
  • 【QoS预测方向】利用数据增强进行QoS预测
    论文题目:LeveragingDataAugmentationforServiceQoSPrediction inCyber-physicalSystems问题:缺乏QoS值限制了推荐性能,并且用户通过调用所有服务来获取QoS值是很耗时的。现有QoS预测模型都不能有效解决数据稀疏问题。解决办法:提出了一种新的两阶段QoS预测模型。第一......
  • 题目26:利用递归方法求 5的阶乘
    题目:利用递归方法求 5! 。deffactorial_fun(integer):ifinteger-1==0:return1returninteger*factorial_fun(integer-1)print(f'5!={factorial_fun(5)}')https://blog.csdn.net/run_noob_vip/category_11598442.html题目26+......
  • Redis使用lua脚本实现库存扣减
    为什么使用Lua脚本为什么能合并多个原子操作?Redis官方文档:https://redis.io/docs/manual/programmability/eval-intro/ Redis保证脚本的原子执行。在执行脚本时,所有服务器活动在其整个运行期间都被阻止。这些语义意味着脚本的所有效果要么尚未发生,要么已经发生。脚本提供了......
  • 人脸识别追踪。 图像采集识别和电机驱动系统,利用openmv图像识别对人脸
    人脸识别追踪。图像采集识别和电机驱动系统,利用openmv图像识别对人脸进行实时采集,采集信号传入到单片机,根据分析结果利用matlab-PID算法控制电机系统跟随人脸运动,自动检测追踪ID:482800621183256282......