使用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); } }