orderNo生成增加redis锁

yun-zuoyi
nies 4 years ago
parent ea8ec0ed18
commit faf60dd3e5

@ -12,6 +12,7 @@ import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder;
import cn.estsh.impp.framework.boot.util.ImppRedis;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
@ -67,43 +68,47 @@ public class SynchronizedService implements ISynchronizedService {
@Override
public synchronized List<SysOrderNoRule> nextOrderNo(String code, int num) {
//先拿规则
SysOrderNoRule codeRole = sysOrderNoRuleService.getSysOrderNoRuleByCode(code);
if (codeRole == null) {
throw ImppExceptionBuilder.newInstance()
.setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
.setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
.setErrorDetail("[" + code + "]规则代码不存在存在")
.setErrorSolution("请重新输入规则代码")
.build();
} else if (codeRole.getOrderNoRuleStatus() == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) {
throw ImppExceptionBuilder.newInstance()
.setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
.setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
.setErrorDetail("[" + code + "]单号规则已禁用")
.setErrorSolution("请重新输入规则代码")
.build();
}
sysOrderNoRuleService.detachSysOrderNoRule(codeRole);
String orderNoTemplate = OrderNoMakeUtil.getOrderNoTemplate(codeRole);
String redisKey = REDIS_PREFIX_LOCK_GET_ORDER_NO + ":" + code + ":" + orderNoTemplate;
long orginSerialNo = codeRole.getSerialNo();
if (codeRole.getSerialNo() < 0 || OrderNoMakeUtil.isCycleByPrefix(codeRole, orderNoTemplate)) {
orginSerialNo = 0;
}
long incr = codeRole.getSerialNoIncrement() * num;
//缓存增加
//先判断redis是否存在如果不存在则用默认初始值+步长*数量,如果存在,则添加步长 * 数量
codeRole.setSerialNo(redisRes.putObjAdditional(redisKey, orginSerialNo, incr) - incr);
// 设置缓存有效期
redisRes.expire(redisKey, PlatformConstWords.REDIS_EXPIRE_SECONDS);
// 生成单号更缓存
List<SysOrderNoRule> orderNoRuleList = sysOrderNoRuleService.doGetSysOrderNoRuleByNum(codeRole, orderNoTemplate, num);
String lockKey = CommonConstWords.REDIS_PREFIX_LOCK_GET_ORDER_NO + ":" + "LOCK" + ":" + code;
RLock rLock = (RLock) redisRes.getLock(lockKey);
rLock.lock();
try {
SysOrderNoRule codeRole = sysOrderNoRuleService.getSysOrderNoRuleByCode(code);
if (codeRole == null) {
throw ImppExceptionBuilder.newInstance()
.setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
.setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION_DATA_NOT_EXIT.getCode())
.setErrorDetail("[" + code + "]规则代码不存在存在")
.setErrorSolution("请重新输入规则代码")
.build();
} else if (codeRole.getOrderNoRuleStatus() == CommonEnumUtil.TRUE_OR_FALSE.FALSE.getValue()) {
throw ImppExceptionBuilder.newInstance()
.setSystemID(CommonEnumUtil.SOFT_TYPE.CORE.getCode())
.setErrorCode(ImppExceptionEnum.VARIFY_EXCEPTION.getCode())
.setErrorDetail("[" + code + "]单号规则已禁用")
.setErrorSolution("请重新输入规则代码")
.build();
}
sysOrderNoRuleService.detachSysOrderNoRule(codeRole);
String orderNoTemplate = OrderNoMakeUtil.getOrderNoTemplate(codeRole);
String redisKey = REDIS_PREFIX_LOCK_GET_ORDER_NO + ":" + code + ":" + orderNoTemplate;
long orginSerialNo = codeRole.getSerialNo();
if (codeRole.getSerialNo() < 0 || OrderNoMakeUtil.isCycleByPrefix(codeRole, orderNoTemplate)) {
orginSerialNo = 0;
}
long incr = codeRole.getSerialNoIncrement() * num;
//缓存增加
//先判断redis是否存在如果不存在则用默认初始值+步长*数量,如果存在,则添加步长 * 数量
codeRole.setSerialNo(redisRes.putObjAdditional(redisKey, orginSerialNo, incr) - incr);
// 设置缓存有效期
redisRes.expire(redisKey, PlatformConstWords.REDIS_EXPIRE_SECONDS);
// 生成单号更缓存
List<SysOrderNoRule> orderNoRuleList = sysOrderNoRuleService.doGetSysOrderNoRuleByNum(codeRole, orderNoTemplate, num);
// FIXME 松下推送量太大并且该记录无意义 先注释
// try {
@ -112,8 +117,15 @@ public class SynchronizedService implements ISynchronizedService {
// LOGGER.error("单号记录推送异常", e);
// }
// 生成单号更缓存
return orderNoRuleList;
// 生成单号更缓存
return orderNoRuleList;
} catch (Exception e) {
LOGGER.error("生成单号失败,单号代码:{},num:{}", code, num, e);
} finally {
if (rLock.isHeldByCurrentThread()) {
rLock.unlock();
}
}
return null;
}
}

@ -0,0 +1,67 @@
package test.cn.estsh.i3plus.core.apiservice.serviceimpl.busi;
import cn.estsh.i3plus.core.api.iservice.base.ISynchronizedService;
import cn.estsh.i3plus.core.apiservice.serviceimpl.base.SynchronizedService;
import cn.estsh.i3plus.platform.common.util.CommonConstWords;
import cn.estsh.i3plus.pojo.platform.bean.SysOrderNoRule;
import cn.estsh.impp.framework.boot.util.ImppRedis;
import cn.estsh.impp.framework.run.ImppGo;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.util.ObjectUtils;
import org.testng.TestRunner;
import org.testng.annotations.Test;
import javax.annotation.Resource;
import java.util.Random;
/**
* @author ns
* orderNo
* @create 2021/9/15 0015 13:46
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ImppGo.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestSynchronizedService extends AbstractTestNGSpringContextTests {
@Autowired
private ISynchronizedService synchronizedService;
@Resource(name = CommonConstWords.IMPP_REDIS_RES)
private ImppRedis resRedis;
public static String orderNoKey = CommonConstWords.REDIS_PREFIX_LOCK_GET_ORDER_NO + ":" + "LOCK" + ":" + "PO_ORDER_NO" + ":" + "ORDERNO";
public static String serialNoKey = CommonConstWords.REDIS_PREFIX_LOCK_GET_ORDER_NO + ":" + "LOCK" + ":" + "PO_ORDER_NO" + ":" + "SERIALNO";
@Test(threadPoolSize = 5)
public void getOrderNo() {
while (true) {
try {
SysOrderNoRule sysOrderNoRule = synchronizedService.nextOrderNo("PO_ORDER_NO");
System.out.println(sysOrderNoRule);
System.out.println(sysOrderNoRule.getOrderNo());
System.out.println(sysOrderNoRule.getSerialNo());
if (!ObjectUtils.isEmpty(resRedis.getHash(orderNoKey + ":ORDERNO" ,sysOrderNoRule.getOrderNo()))){
throw new Exception("订单号重复");
}else{
resRedis.putHash(orderNoKey + ":ORDERNO",sysOrderNoRule.getOrderNo(), System.currentTimeMillis());
}
if (!ObjectUtils.isEmpty(resRedis.getHash(orderNoKey + ":SERIALNO", String.valueOf(sysOrderNoRule.getSerialNo())))){
throw new Exception("订单号重复");
}else {
resRedis.putHash(orderNoKey + ":SERIALNO", String.valueOf(sysOrderNoRule.getSerialNo()), System.currentTimeMillis());
}
Thread.sleep(new Random().nextInt(20));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Loading…
Cancel
Save