• 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演示:

    加锁处理方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    @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加锁成功
            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);
            }
        }
    }

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    //秒杀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)));
     
    }
  • 相关阅读:
    接口框架项目示例
    接口框架开发流程总结
    requests库的简单使用
    使用flask创建简单的接口
    session和token
    解决log函数生成重复log的问题
    自定义封装logging参考
    织梦dedecms做的网站首页标题篡改跳转赌博网站解决方案
    织梦网站安全查杀
    织梦重置密码的方法和织梦网站后台登陆账号修改方法
  • 原文地址:https://www.cnblogs.com/xiaoshuaidiboke/p/8066712.html
Copyright © 2020-2023  润新知