redisを使用して高同時シーンを処理する

7288 ワード

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