添加依赖
配置文件application.yml
db:
redis:
url: 地址
password: 密码
创建分布式锁类:
package com.juseerp.business.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
/**
-
redis 分布式锁
-
@Auther: zhouyc
-
@Date: 2022/3/4
*/
@Component
@Slf4j
public class RedisLockUtil {@Autowired
private RedisTemplate redisTemplate;
/**- 加锁,自旋重试三次
- @return
*/
public boolean lock(String lockKey,String requestId) {
boolean locked = false;
int tryCount = 3;
while (!locked && tryCount > 0) {
locked = redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, 3, TimeUnit.MINUTES);
tryCount–;
try {
Thread.sleep(300);
} catch (InterruptedException e) {
log.error(“线程被中断” + Thread.currentThread().getId(), e);
Thread.currentThread().interrupt();
}
}
return locked;
}
/**
- 非原子解锁,可能解别人锁,不安全
- @return
*/
public boolean unlock(String lockKey,String requestId) {
boolean releaseLock = false;
String oldRequestId = (String) redisTemplate.opsForValue().get(lockKey);
if (requestId.equals(oldRequestId)) {
releaseLock = redisTemplate.delete(lockKey);
}
return releaseLock;
}
/**
- 使用lua脚本解锁,不会解除别人锁
- @return
*/
public boolean unlockLua(String lockKey,String requestId) {
DefaultRedisScript redisScript = new DefaultRedisScript();
//用于解锁的lua脚本位置
redisScript.setLocation(new ClassPathResource(“unlock.lua”));
redisScript.setResultType(Long.class);
//没有指定序列化方式,默认使用上面配置的
Object result = redisTemplate.execute(redisScript, Arrays.asList(lockKey), requestId);
return result.equals(Long.valueOf(1));
}
}
实现锁:
public void lockStock() {
String redisKey = BusinessConstant.LOCK_PRODUCT_STOCK_PRE_KEY + temp.getStockId();
String val = UUIDUtil.getUUID();
try {
if (redisLockUtil.lock(redisKey, val)) {
需要执行方法
} else {
throw new GlobleException(String.format(“库存: %s锁定失败”, storeId)); }
} finally {
redisLockUtil.unlockLua(redisKey, val);
}
}