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

  • 相关阅读:
    如何正确设置数据库连接池的大小
    spring生命周期
    Spring高级进阶:BeanFactoryPostProcessor
    Spring Bean的生命周期(非常详细)
    表达式求值相关算法
    golang 命令行参数解析 hflag
    golang 标准命令行解析库 flag
    docker consul 环境搭建
    docker etcd 环境搭建
    mysql 事务
  • 原文地址:https://www.cnblogs.com/jarjune/p/10839599.html
Copyright © 2011-2022 走看看