zoukankan      html  css  js  c++  java
  • 用压测模拟并发、并发处理(synchronized,redis分布式锁)

    使用工具:Apache an

    测压命令: ab -n 100 -c 100 http://www.baidu.com -n代表模拟100个请求,-c代表模拟100个并发,相当于100个人同时访问

        ab -t 60 -c 100 http://www.baidu.com 60秒100个并发,不断发送请求

      

    并发处理:

    1.加synchronized锁单线程处理、缺点: 无法做到细粒度控制,处理速度也会很慢  只适合单点的情况

    2.redis分布式锁:

    可以支撑每秒10多万的并发,支持分布式,可以更细粒的控制代码(多台机器上多个线程对一个数据进行操作的互斥)

    SETNX key value

    将key设置值为value,如果key不存在,这种情况下等同于SET命令,当key存在时,什么也不做

    GETSET key value

    自动将key对应到value并且返回原来key和对应的value,如果key存在但是对应的value不是字符串,就返回错误

    DEMO演示:

    加锁处理方法:

    @Component
    @Slf4j
    public class RedisLock {
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
        //加锁
        /*
        * @param key id
        * @param value 当前时间+超时时间
        *
        * */
        public  boolean lock(String key,String value){
            if (stringRedisTemplate.opsForValue().setIfAbsent(key,value)){
                return true;//加锁成功就返回true
            }
            //不加下面这个可能出现死锁情况
         //代码value加了过期时间* @param value 当前时间+超时时间
        //获取上一个锁的时间,并判断是否小于当前时间,小于就下一步判断,就返回true加锁成功
            //currentValue=A 这两个线程的value都是B 其中一个线程拿到锁
            String currentValue=stringRedisTemplate.opsForValue().get(key);
            //如果锁过期
            if (!StringUtils.isEmpty(currentValue)
                    && Long.parseLong(currentValue)<System.currentTimeMillis()){//存储时间要小于当前时间
        //出现死锁的另一种情况,当多个线程进来后都没有返回true,接着往下执行,执行代码有先后,而if判断里只有一个线程才能满足条件
        //oldValue=currentValue
        //多个线程进来后只有其中一个线程能拿到锁(即oldValue=currentValue),其他的返回false
                //获取上一个锁的时间
                String oldValue=stringRedisTemplate.opsForValue().getAndSet(key,value);
                if (!StringUtils.isEmpty(oldValue)&& oldValue.equals(currentValue)){//上一个时间不为空,并且等于当前时间
                    return true;
                }
    
            }
            return  false;//失败返回false
        }
    
    
    
        //解锁
        public void unlock(String key,String value){//执行删除可能出现异常需要捕获
            try {
                String currentValue = stringRedisTemplate.opsForValue().get(key);
                if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {//如果不为空,就删除锁
                    stringRedisTemplate.opsForValue().getOperations().delete(key);
                }
            }catch (Exception e){
                log.error("[redis分布式锁] 解锁",e);
            }
        }
    }
    

      

      

    //秒杀demo
    pprivate static final int TIMEOUT=10*1000;//超时时间设置为10s
    @Autowrite
    private RedisLock redisLock;
    public void method(String  id){
    
    //加锁-死锁出现:即在加锁后运行程序出现意外报了异常,而此时还没调用解锁方法
    //那么在下一个线程调用加锁方法是就不能set,直接返回fale,然后一直停留在加锁失败状态 这就出现了死锁
    long time=System.currentTimeMillis()+TIMEOUT;
    //如果加锁不成功就抛出异常
    
     if(!redisLock.lock.get(id,String.valueof(time))){
    throw new WechatSellException(101,"哎哟喂,人也太多了,换个姿势再试试");
    }
    //加锁成功就实现业务代码处理
    
    //1.查询该商品库存,为0表示活动结束
    
    
    //2.下单
    
    
    3.扣库存
    
    
    //解锁
    redisLock.unlock(id,String.valueof(time)));
    
    }
    

      

      

      

       

  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/tanghao666/p/8064998.html
Copyright © 2011-2022 走看看