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