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

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;

 

}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值