使用redis 处理高并发场景

1.原理: 当同一个用户获取锁之后,会让该用户一直持有锁。同样 的用户再次获取,会根据原子性 ,lock返回true。

 /**
     * 获取锁(非公平锁), 默认获取超时为2分钟
     */
    public boolean lock(){
        return lock(GETLOCK_TIMEOUT/1000);
    }
    /**
     * 获取锁(非公平锁), 获取超时为timeoutSeconds秒
     */
    public boolean lock(int timeoutSeconds){
        int timeout = timeoutSeconds*1000;
        while (timeout >= 0) {
            //在同一个JVM内,防止出现以下情况:当已经获取此锁的线程实际业务运行时间超过LOCK_EXPIRE_TIMEOUT时,此锁会再被其它线程获取
            if(LOCKED_NAMES.contains(lockname)){
                int sleeptime = random.nextInt(100)+100;
                try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
                timeout -= sleeptime;
                continue;
            }
            //当分布式程序获取同一个锁时,防止出现以下情况:当已经获取此锁的进程(物理机器)实际业务运行时间超过LOCK_EXPIRE_TIMEOUT时,此锁会再被其它进程(物理机器)获取
            String hearbeatFlag = RedisCacheUtil.get(lockname + HEARTBEAT_SUFFIX , String.class );
            if(hearbeatFlag!=null){
                int sleeptime = random.nextInt(100)+100;
                try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
                timeout -= sleeptime;
                continue;
            }
            
            //锁到期时间
            long expires = System.currentTimeMillis() + LOCK_EXPIRE_TIMEOUT + 1;
            boolean ok = setNX(expires);
            if (ok) {
                //System.out.println(Thread.currentThread().getName()+":获得锁成功,通过setNX");
                LOCKED_NAMES.add(lockname);
                locked = true;
                return locked;
            }
            //获取当前锁信息
            RedisLockValue redisLockValue = get();
            if (redisLockValue != null && redisLockValue.getExpireTime() < System.currentTimeMillis()) {
                //利用getSet的原子性操作来设置并获取到旧值
                RedisLockValue oldRedisLockValue = getSet(expires);
                //最先设置的获取锁
                if (oldRedisLockValue != null && oldRedisLockValue.getToken().equals(redisLockValue.getToken())) {
                    //System.out.println(Thread.currentThread().getName()+":获得锁成功,通过getSet");
                    LOCKED_NAMES.add(lockname);
                    locked = true;
                    return locked;
                }
            }
            //防止饥饿线程出现 采用随机休眠时间
            int sleeptime = random.nextInt(100)+100;
            try{Thread.sleep(sleeptime);} catch (InterruptedException e) {}
            timeout -= sleeptime;
        }
        
        //如果已经超时,但只是因为此时缓存还有值,因为反序列化异常导致GET取不到时,解决死锁问题
        try{Thread.sleep(300);} catch (InterruptedException e) {}
        RedisLockValue redisLockValue = get();
        if(redisLockValue==null){
            //强制删掉即可
            LOCKED_NAMES.remove(lockname);
            RedisCacheUtil.delete(lockname);
            RedisCacheUtil.delete( lockname + HEARTBEAT_SUFFIX );
        }
        return locked;
    }
原文地址:https://www.cnblogs.com/thinkingandworkinghard/p/10627994.html