在分布式环境下解决商品不出现超卖的关键就说对上面每一笔库存在进行操作的时候需要进行锁,然后进行扣减,并且释放锁:
上关键代码:
@ServiceLock(lockKey="Commodity")
@Transactional
public void killHandler() {
int stachId = 1;//库存编号
int stachNum = stachModel.getStachNum(stachId);//查看库存是否足够
if(stachNum > 0) {//库存充足
stachNum -= 1; //每次购买一件
Map<String,Object> inserParam = new HashMap();
inserParam.put("id", Math.random() * 100000000);
inserParam.put("num", 1);
inserParam.put("stachid", stachId);
inserParam.put("version", 0);
orderModel.insert(inserParam);
stachModel.modelNum(stachId, stachNum);
}
}
关键核心是:上分布式锁
@Around("@annotation(com.sloth.kill.annotaion.ServiceLock)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (method.isAnnotationPresent(ServiceLock.class)) {
ServiceLock annotation = method.getAnnotation(ServiceLock.class);
String lockKey = annotation.lockKey();
log.info(lockKey);
RLock lock = redissonClient.getLock(lockKey);
Object obj = null;
try{
lock.lock();
obj = joinPoint.proceed();
}catch(Throwable e){
e.printStackTrace();
throw new Throwable(e);
}finally{
lock.unlock();
}
return obj;
}else {
return joinPoint.proceed();
}
}
升级为 注解读取参数输入内容
@Around("@annotation(com.sy.store.annotation.LockAnnotation)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (method.isAnnotationPresent(LockAnnotation.class)) {
Parameter[] parameters = method.getParameters();
LockAnnotation annotation = method.getAnnotation(LockAnnotation.class);
EvaluationContext ctx = new StandardEvaluationContext();
if(parameters != null && parameters.length > 0) {
for (int i = 0; i < parameters.length; i++) {
ctx.setVariable(parameters[i].getName(), joinPoint.getArgs()[i]);
}
}
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
Object value = parser.parseExpression(annotation.value()).getValue(ctx);
RLock lock = redissonClient.getLock(value.toString());
Object obj = null;
try{
lock.lock();
obj = joinPoint.proceed();
}catch(Throwable e){
e.printStackTrace();
throw new Throwable(e);
}finally{
lock.unlock();
}
return obj;
}
return joinPoint.proceed();
}