美文网首页
分布式redis锁

分布式redis锁

作者: wanggs | 来源:发表于2019-04-03 23:14 被阅读0次
package com.wanggs.sell.service.impl;

import com.wanggs.sell.enums.ResultEnum;
import com.wanggs.sell.exception.SellException;
import com.wanggs.sell.service.RedisLock;
import com.wanggs.sell.service.SeckillService;
import com.wanggs.sell.util.KeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Wgs
 * @version 1.0
 * @create:2019/04/02
 */
@Service
public class SeckillServiceImpl implements SeckillService {
    @Autowired
    private RedisLock redisLock;
    private static int TIMEOUT = 10 * 1000;
    static Map<String, Integer> products;
    static Map<String, Integer> stock;
    static Map<String, String> orders;
    static {
        /**
         * 模拟多张表 商品信息表 库存表 秒杀成功订单表
         */
        products = new HashMap<>();
        stock = new HashMap<>();
        orders = new HashMap<>();
        products.put("123456", 1000);
        stock.put("123456", 1000);
    }

    private String queryMap(String productId) {
        return "双十一秒杀活动,限量份:" + products.get(productId) + "还剩" + stock.get(productId) + " 份" + "" +
                "该商品成功下单用户数目:" + orders.size() + " 人";
    }
    @Override
    public String query(String productId) {
        return this.queryMap(productId);
    }

    @Override
    public  void orderProductMockDiffUser(String productId) {
        // 加锁
        Long time = System.currentTimeMillis() + TIMEOUT;
       if (!redisLock.lock(productId, String.valueOf(time))){
            throw new SellException(101,"人太多了,换个姿势抢!!");
        }
        // 查询商品库存,为0 秒杀结束
        int stockNum = stock.get(productId);
        if (stockNum == 0) {
            throw new SellException(ResultEnum.PRODUCT_STOCK_ERROR);
        } else {
            // 下单(模拟openId不相同)
            orders.put(KeyUtil.genUniqueKey(), productId);
            // 减库存
            stockNum = stockNum - 1;
            try {
                //模拟插入数据库
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            stock.put(productId, stockNum);
        }
        System.out.println("-------恭喜抢到-------");
        redisLock.unLock(productId, String.valueOf(time));

    }

}


package com.wanggs.sell.service;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @author Wgs
 * @version 1.0
 * @create:2019/04/02
 */
@Component
@Slf4j
public class RedisLock {
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 加锁
     *
     * @param key
     * @param value 当前时间+超时时间
     * @return
     */
    public boolean lock(String key, String value) {
        if (redisTemplate.opsForValue().setIfAbsent(key, value)) {
            return true;
        }
        String currentValue = redisTemplate.opsForValue().get(key);
        // 如果说过期
        if (StringUtils.isNotBlank(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()) {
            // 获取上一个锁
            String oldValue = redisTemplate.opsForValue().getAndSet(key, value);
            if (StringUtils.isNotBlank(oldValue) && oldValue.equals(currentValue)) {
                return true;
            }
        }

        return false;
    }

    public void unLock(String key, String value) {
        try {
            String currentValue = redisTemplate.opsForValue().get(key);
            if (StringUtils.isNotBlank(currentValue) && value.equals(currentValue)) {
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        } catch (Exception e) {
            log.error("[redis 分布式解锁] 异常:{}", e);
        }

    }
}


相关文章

网友评论

      本文标题:分布式redis锁

      本文链接:https://www.haomeiwen.com/subject/rsfxiqtx.html