zoukankan      html  css  js  c++  java
  • 浅谈redis分布式锁用法

    使用redis的setnx命令进行实现

    @Component
    @Slf4j
    public class RedisLock {
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        /**
         * 加锁
         *
         * @param key
         * @param value
         * @return
         */
        public boolean lock(String key, String value) {
            if (stringRedisTemplate.opsForValue().setIfAbsent(key, value)) {
                return true;
            }
            String currentValue = stringRedisTemplate.opsForValue().get(key);
            //防止死锁
            if (!StringUtils.isEmpty(currentValue)
                    && Long.parseLong(currentValue) < System.currentTimeMillis()) {
                String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);
                if (!StringUtils.isEmpty(oldValue)
                        && oldValue.equals(currentValue)) {
                    return true;
                }
    
            }
            return false;
        }
    
        /**
         * 解锁
         * @param key
         * @param value
         */
        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

    @Service
    public class SecKillServiceImpl implements SeckillService {
        //超时时间10秒
        private static final int       TIMEOUT = 10 * 1000;
        @Autowired
        private              RedisLock redisLock;
    
        static Map<String, Integer> products;
        static Map<String, Integer> stock;
        static Map<String, String>  orders;
    
        {
            products = new HashMap<>();
            stock = new HashMap<>();
            orders = new HashMap<>();
            products.put("123456", 100000);
            stock.put("123456", 100000);
        }
    
        private String queryMap(String productId) {
            return "国庆活动,皮蛋粥特价,限量份"
                    + products.get(productId)
                    + "还剩:" + stock.get(productId) + "份"
                    + "该商品成功下单用户数目:"
                    + orders.size() + "人";
        }
    
        @Override
        public  void orderProductMockDiffUser(String productId) {
            Long time = System.currentTimeMillis() + TIMEOUT;
            //加锁
            if (!redisLock.lock(productId, String.valueOf(time))) {
                throw new SellException(101, "哎呦喂,人也太多了,在试试");
            }
    
            Integer stockNum = stock.get(productId);
            if (stockNum == 0) {
                throw new SellException(100, "活动结束");
            } else {
                //下单
                orders.put(KeyUtil.genUniqueKey(), productId);
                //减库存
                stockNum = stockNum - 1;
                try {
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                stock.put(productId, stockNum);
            }
            //解锁
            redisLock.unlock(productId, String.valueOf(time));
        }
    
        @Override
        public String querySecKillProductInfo(String productId) {
            return queryMap(productId);
        }
    }
  • 相关阅读:
    1.根据文件路径文件或文件夹图标获取 2.根据后缀获取系统图标
    多线程处理一个问题和多个问题
    C#汉字转换拼音技术详解
    委托小实例
    Winform 线程
    word 转换成 pdf
    几道算法题目
    双色球生成器
    c# Invoke和BeginInvoke
    C# 委托和事件2
  • 原文地址:https://www.cnblogs.com/panbingqi/p/11281573.html
Copyright © 2011-2022 走看看