Commit 56499d93 authored by 刘林's avatar 刘林

fix(JG):一码通添加锁修改为Redisson

parent 803ae4f5
......@@ -6,6 +6,8 @@ import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentCategoryEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.CategoryOtherInfoMapper;
import com.yeejoin.amos.boot.module.ymt.api.service.IGenerateCodeService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
......@@ -33,17 +35,19 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
private static final String LOCK_KEY_SUPERVISORY = "sequence_lock_supervisory";
private static final String SEQUENCE_TYPE_UR = "%05d";
private static final String SEQUENCE_TYPE = "%07d";
private static final long LOCK_EXPIRATION_SECONDS = 600;
private final RedisTemplate<String, String> redisTemplate;
private final StringRedisTemplate stringRedisTemplate;
private final CategoryOtherInfoMapper categoryOtherInfoMapper;
private final RedissonClient redissonClient;
private String rulePrefix = "";
public GenerateCodeServiceImpl(RedisTemplate<String, String> redisTemplate, StringRedisTemplate stringRedisTemplate, CategoryOtherInfoMapper categoryOtherInfoMapper) {
public GenerateCodeServiceImpl(RedisTemplate<String, String> redisTemplate, StringRedisTemplate stringRedisTemplate, CategoryOtherInfoMapper categoryOtherInfoMapper, RedissonClient redissonClient) {
this.redisTemplate = redisTemplate;
this.redissonClient = redissonClient;
this.stringRedisTemplate = stringRedisTemplate;
this.categoryOtherInfoMapper = categoryOtherInfoMapper;
}
/**
* 生成申请单编号(13位,GZ20231214000)
*
......@@ -109,9 +113,11 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
private String generateSupervisorySequence(String sequenceKey) {
// 使用分布式锁,确保在并发情况下只有一个线程能够生成顺序码
Boolean lockAcquired = obtainLock(GenerateCodeServiceImpl.LOCK_KEY_SUPERVISORY);
if (Boolean.TRUE.equals(lockAcquired)) {
try {
RLock lock = redissonClient.getLock(LOCK_KEY_SUPERVISORY);
try {
log.info("尝试获取锁: {}", lock.tryLock(10, TimeUnit.SECONDS));
if (lock.isLocked()) {
// 获取当前顺序码
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
String currentSequenceStr = valueOps.get(sequenceKey);
......@@ -126,16 +132,21 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
// 更新顺序码
valueOps.set(sequenceKey, formattedSequence);
return sequenceKey + "-" + formattedSequence;
} finally {
releaseLock(GenerateCodeServiceImpl.LOCK_KEY_SUPERVISORY);
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
}
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
throw new RuntimeException("Thread interrupted while acquiring lock", e);
} finally {
lock.unlock(); // 释放锁
log.info("释放锁");
}
}
/**
* 监管码为空的话,初始化Redis
*
* @param sequenceKey key
* @return 顺序码
*/
......@@ -166,10 +177,12 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
* @return List
*/
public List<String> generateBatchSequence(String sequenceKey, int batchSize) {
// 使用分布式锁,确保在并发情况下只有一个线程能够生成顺序码
Boolean lockAcquired = obtainLock(LOCK_KEY_AF);
if (Boolean.TRUE.equals(lockAcquired)) {
try {
RLock lock = redissonClient.getLock(LOCK_KEY_AF);
try {
log.info("尝试获取锁: {}", lock.tryLock(10, TimeUnit.SECONDS));
if (lock.isLocked()) {
// 获取当前顺序码
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
String currentSequenceStr = valueOps.get(sequenceKey);
......@@ -192,12 +205,16 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
}
return sequenceList;
} finally {
releaseLock(LOCK_KEY_AF);
} else {
// 获取锁失败,可以选择重试或采取其他策略
throw new RuntimeException("Failed to acquire lock for sequence generation");
}
} else {
// 获取锁失败,可以选择重试或采取其他策略
throw new RuntimeException("Failed to acquire lock for sequence generation");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
throw new RuntimeException("Thread interrupted while acquiring lock", e);
} finally {
lock.unlock(); // 释放锁
log.info("释放锁");
}
}
......@@ -211,9 +228,13 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
*/
public String generateSequence(String sequenceKey, String sequenceType, String lockKey) {
// 使用分布式锁,确保在并发情况下只有一个线程能够生成顺序码
Boolean lockAcquired = obtainLock(lockKey);
if (Boolean.TRUE.equals(lockAcquired)) {
try {
RLock lock = redissonClient.getLock(lockKey);
try {
log.info("尝试获取锁: {}", lock.tryLock(10, TimeUnit.SECONDS));
if (lock.isLocked()) {
// 获取当前顺序码
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
String currentSequenceStr = valueOps.get(sequenceKey);
......@@ -236,40 +257,47 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
log.info("===================>返回《{}》顺序码:{}<===================", sequenceKey, result);
return result;
} finally {
releaseLock(lockKey);
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
}
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
throw new RuntimeException("Thread interrupted while acquiring lock", e);
} finally {
lock.unlock(); // 释放锁
log.info("释放锁");
}
}
/**
* 生成顺序码
*
* @param sequenceKey redisKey
* @param sequenceKey Redis Key
* @param sequenceType 生成码类型
* @param lockKey redis锁
* @return s
* @param lockKey Redis锁Key
* @return 生成的顺序码
*/
public String generateElevatorSequence(String sequenceKey, String sequenceType, String lockKey) {
// 使用分布式锁,确保在并发情况下只有一个线程能够生成顺序码
Boolean lockAcquired = obtainLock(lockKey);
if (Boolean.TRUE.equals(lockAcquired)) {
try {
RLock lock = redissonClient.getLock(lockKey);
try {
log.info("尝试获取锁: {}", lock.tryLock(10, TimeUnit.SECONDS));
if (lock.isLocked()) {
// 获取当前顺序码
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
String currentSequenceStr = valueOps.get(sequenceKey);
// 如果为空,则初始化为0
if (currentSequenceStr == null) {
currentSequenceStr = EquipmentCategoryEnum.getCodeByValue(sequenceKey);
log.info("===================>获取《{}》初始码:{}<===================", sequenceKey, currentSequenceStr);
return currentSequenceStr;
String initialCode = EquipmentCategoryEnum.getCodeByValue(sequenceKey);
log.info("===================>获取《{}》初始码:{}<===================", sequenceKey, initialCode);
return initialCode;
}
Long currentSequence = Long.parseLong(currentSequenceStr);
Long currentSequence = Long.parseLong(currentSequenceStr);
log.info("===================>获取《{}》当前顺序码:{}<===================", sequenceKey, currentSequenceStr);
currentSequence++;
// 生成顺序码
String formattedSequence = String.format(sequenceType, currentSequence);
......@@ -277,12 +305,15 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
// 更新顺序码
valueOps.set(sequenceKey, formattedSequence);
return formattedSequence;
} finally {
releaseLock(lockKey);
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
}
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
throw new RuntimeException("Thread interrupted while acquiring lock", e);
} finally {
lock.unlock(); // 释放锁
log.info("释放锁");
}
}
......@@ -296,9 +327,11 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
*/
public boolean reduceSequence(String sequenceKey, String sequenceType, String lockKey) {
// 使用分布式锁,确保在并发情况下只有一个线程能够生成顺序码
Boolean lockAcquired = obtainLock(lockKey);
if (Boolean.TRUE.equals(lockAcquired)) {
try {
RLock lock = redissonClient.getLock(lockKey);
try {
lock.lock(); // 获取锁
log.info("尝试获取锁: {}", lock.tryLock(10, TimeUnit.SECONDS));
if (lock.isLocked()) {
// 获取当前顺序码
ValueOperations<String, String> valueOps = redisTemplate.opsForValue();
String currentSequenceStr = valueOps.get(sequenceKey);
......@@ -321,36 +354,16 @@ public class GenerateCodeServiceImpl implements IGenerateCodeService {
log.warn("===================>无法回退《{}》顺序码,当前顺序码已为0<===================", sequenceKey);
return false; // 无法回退,当前顺序码已为0
}
} finally {
releaseLock(lockKey);
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
}
} else {
throw new RuntimeException("Failed to acquire lock for sequence generation");
}
}
/**
* 分布式锁
*
* @param lockKey lockKey
* @return bool
*/
private Boolean obtainLock(String lockKey) {
Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(lockKey, LOCK_VALUE);
if (lockAcquired != null && lockAcquired) {
redisTemplate.expire(lockKey, LOCK_EXPIRATION_SECONDS, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 保持中断状态
throw new RuntimeException("Thread interrupted while acquiring lock", e);
} finally {
lock.unlock(); // 释放锁
log.info("释放锁");
}
return lockAcquired;
}
/**
* 释放锁
*
* @param lockKey lockKey
*/
private void releaseLock(String lockKey) {
redisTemplate.delete(lockKey);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment