正文
浅谈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);
}
}