redis分布式锁的设计和使用demo

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20009015/article/details/84647302

package com.nchu.common.utils;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.stereotype.Component;

import org.springframework.util.StringUtils;

@Component

@Slf4j

public class RedisLock {

@Autowired

private StringRedisTemplate redisTemplate;

/**

* 加锁

* @param key

* @param value 当前时间+超时时间

* @return

*/

public boolean lock(String key, String value) {

//setIfAbsent 可以设置key和value 则返回true 否则返回false key是商品id value值为当前时间+超时时间

if(redisTemplate.opsForValue().setIfAbsent(key, value)) {

return true;

}

String currentValue = redisTemplate.opsForValue().get(key);

//如果锁过期

if (!StringUtils.isEmpty(currentValue)

&& Long.parseLong(currentValue) < System.currentTimeMillis()) {

//获取上一个锁的时间 并把当前最新的时间+超时时间放进去

String oldValue = redisTemplate.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 = redisTemplate.opsForValue().get(key);

if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {

redisTemplate.opsForValue().getOperations().delete(key);

}

}catch (Exception e) {

log.error("【redis分布式锁】解锁异常, {}", e);

}

}

}

使用

/**

* 用户付款时候减去库存

*/

private int subStock(String OrderId) {

List<OrderDetail> orderDetailList = orderDetailMapper.selectByOrderId(OrderId);

List<String> ProductIds = orderDetailList.stream().map(x -> x.getProductId()).collect(Collectors.toList());

Map<String, OrderDetail> productIdAndOrderDetail = new HashMap<>();

orderDetailList.forEach(x -> productIdAndOrderDetail.put(x.getProductId(), x));

for (String id : ProductIds) {

// 分布式锁 加锁

Long currentDate = System.currentTimeMillis() + 5000; //设置加锁时间

Boolean result = redisLock.lock(id, currentDate.toString());

//不成功重试

while (!result) {

currentDate = System.currentTimeMillis() + 5000; //设置加锁时间

result = redisLock.lock(id, currentDate.toString());

}

ProductInfo productInfo = productInfoMapperEx.selectByPrimaryKey(id);

OrderDetail orderDetail=productIdAndOrderDetail.get(id);

Integer nowStockNum = productInfo.getProductStock() - orderDetail.getProductQuantity();

if (nowStockNum <= 0) { //小于0 说明库存不足

return -1;

}

productInfo.setProductStock(nowStockNum);

//更新库存

productInfoMapperEx.updateByPrimaryKey(productInfo);

//解锁

redisLock.unlock(id, currentDate.toString());

}

return 1;

}

猜你喜欢

转载自blog.csdn.net/qq_20009015/article/details/84647302