zoukankan      html  css  js  c++  java
  • 使用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;
        }
  • 相关阅读:
    Unity3D_08_XML文件创建,读取,修改,添加
    Unity3D_07_日志、文本打印
    Unity3D_06_根据Transform、GameObject和Tag获取子对象集合
    Unity3D_05_理解Unity的新GUI系统(UGUI)
    Unity3D_04_GameObject,Component,Time,Input,Physics
    Unity3D_03_代码及效率优化总结
    Unity3D_02_基类MonoBehaviour/自带函数以及脚本执行的生命周期
    Unity3D_01_各种寻找GameObject方法
    人工智能相关
    ubuntu 安装 typora
  • 原文地址:https://www.cnblogs.com/thinkingandworkinghard/p/10627994.html
Copyright © 2011-2022 走看看