zoukankan      html  css  js  c++  java
  • redis(单机模式)分布式锁的实现【已废弃】

    问题起源:后台刷新token的时候,会有高并发问题。
    即:A发起请求的时候,刷新token时,还未存入redis,此时B发起请求,问题就出现了。

    由于Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,所以本次用redis来解决这个问题。

    INCR key

    为键 key 储存的数字值加上一。
    如果键 key 不存在, 那么它的值会先被初始化为 0 , 然后再执行 INCR 命令。

    伪代码

    
    @RestController
    public class Demo {
    
        private String key = "demo";
    
        class DemoThread extends Thread {
    
            // 是否结束的标识
            private boolean isFinished = false;
    
            public void setFinished(boolean finished) {
                this.isFinished = finished;
            }
    
            @Override
            public void run() {
                for(int i = 0; i < 6; i++) {
                    if(isFinished) {
                        System.out.println("4.已解锁");
                        break;
                    } else {
                        System.out.println("5.续命。。。" + i);
                        template.expire(key, 5, TimeUnit.SECONDS);
                    }
    
                    try {
                        System.out.println("每1秒判断一次是否执行完毕");
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        @RequestMapping("/demo")
        public void demo() {
            Thread thread = new DemoThread();
    
            Random r = new Random();
            try{
                long flag = template.opsForValue().increment(key, 1);
                template.expire(key, 10, TimeUnit.SECONDS);
                
                if(flag == 1) {
    
                    thread.start();
                    if(r.nextInt(10) == 1) {
                        System.out.println("1.执行缓慢");
                        Thread.sleep(5000);
                    } else {
                        System.out.println("2.获取锁");
                    }
                } else {
                    System.out.println("3.未获取锁");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
    
                ((DemoThread) thread).setFinished(true);
                template.opsForValue().increment(key, -1);
            }
        }
    }
    

    解释

    非公平锁,不是按照FIFO(先进先出)的顺序执行。

    • 为了防止死锁,增加了过期时间。
    • 为了防止网络延迟,导致业务还未执行完成,锁就已经失效,所以加了线程监听是否执行完成,如果未完成则续期。
    • 为了防止业务逻辑执行超时(一直未到finally),所以上述只for循环了6次。

    2019-06-20

    由于加锁过程没有保证原子性,已废弃此方法,正式项目已改用redission

  • 相关阅读:
    sun.misc.BASE64Encoder----》找不到jar包的解决方法
    javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint-实体报错
    避免MQ消息重发的简单实现思路
    使用Spring的@Scheduled实现定时任务参数详解
    重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
    安装mysql zip5.7版--安裝
    bzoj3983
    bzoj4044
    bzoj1064
    bzoj4042
  • 原文地址:https://www.cnblogs.com/jarjune/p/10839599.html
Copyright © 2011-2022 走看看