Springboot+Aop註解的方式實現分散式鎖
公司做分散式的訂單業務,需要增加分散式鎖進行競爭資源,需要增加鎖降級功能
簡單實現了一下,支援 SPEL ,有更好的建議盡情提出
註解程式碼:
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheLock {
/**
* 支援 SPEL 表示式
*/
String key();
long expTime() default 10;
TimeUnit timeUnit() default TimeUnit.SECONDS;
}
AOP 切面:
@Slf4j
@Aspect
@Component
public class CacheLockAop {
/**
* 最大等待時間 ms
*/
private static final long MAX_WAIT_TIME = 30000;
@Resource
private Redisson orderRedisson;
@Around("@within(cacheLock) || @annotation(cacheLock)")
public Object cacheLock(ProceedingJoinPoint jp, CacheLock cacheLock) throws Throwable {
Object result = Response.fail(CodeEnum.ERROR.getCode(), CodeEnum.ERROR.getMsg());
boolean locked = false;
try {
String lockKey = CacheKeyConstant.ORDER_LOCK_KEY + this.getLockKey(jp, cacheLock.key());
log.info("CacheLockAop#cacheLock 獲取 key : {}", lockKey);
RLock rLock = orderRedissonExt.getLock(lockKey);
locked = rLock.tryLock(cacheLock.timeUnit().convert(MAX_WAIT_TIME, TimeUnit.MILLISECONDS), cacheLock.expTime(), cacheLock.timeUnit());
if (locked) {
try {
result = jp.proceed();
} finally {
rLock.unlock();
}
} else {
log.error("CacheLockAop#cacheLock 外匯跟單gendan5.com 快取鎖獲取失敗, key : {}", lockKey);
result = Response.fail(CodeEnum.ERROR.getCode(), " 快取鎖獲取失敗,請稍後重試 ");
}
} catch (Throwable e) {
log.error("CacheLockAop#cacheLock ERROR", e);
// 異常後沒有獲取鎖執行業務程式碼
if (!locked) {
log.warn(" 快取鎖新增失敗,降級執行 ...");
result = jp.proceed();
}
}
return result;
}
private String getLockKey(ProceedingJoinPoint jp, String elStr) throws NoSuchMethodException {
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
EvaluationContext context = new StandardEvaluationContext();
String[] paraNameArr = discoverer.getParameterNames(this.getTargetMethod(jp));
Object[] args = jp.getArgs();
for (int i = 0; i < paraNameArr.length; i++) {
context.setVariable(paraNameArr[i], args[i]);
}
ExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression(elStr);
String lockKey = expression.getValue(context, String.class);
if (StringUtils.isBlank(lockKey)) {
throw new RuntimeException("CacheLockAop#getLockKey 獲取 lockKey 為空! ");
}
return lockKey;
}
private Method getTargetMethod(ProceedingJoinPoint pjp) throws NoSuchMethodException {
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method agentMethod = methodSignature.getMethod();
return pjp.getTarget().getClass().getMethod(agentMethod.getName(), agentMethod.getParameterTypes());
}
}
使用方法:
@Override
@CacheLock(key = "#orderReq.srcSystem + '_' + #orderReq.orderId")
public Response<Boolean> submitOrder(OrderReq orderReq) {
// 你的業務程式碼
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946337/viewspace-2783883/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 分散式鎖初窺-分散式鎖的三種實現方式分散式
- redis分散式鎖-spring boot aop+自定義註解實現分散式鎖Redis分散式Spring Boot
- 分散式鎖的多種實現方式分散式
- Redis分散式鎖的正解實現方式Redis分散式
- 分散式鎖的幾種實現方式~分散式
- 分散式鎖概念及實現方式分散式
- 分散式鎖解決併發的三種實現方式分散式
- 分散式鎖的多種實現方式,你瞭解嗎?分散式
- Redis分散式鎖的正確實現方式Redis分散式
- 分散式鎖實現的正確開啟方式分散式
- 基於註解的方式使用spring-integration-redis分散式鎖SpringRedis分散式
- 基於redis和zookeeper的分散式鎖實現方式Redis分散式
- 分散式鎖實現分散式
- 實現分散式鎖分散式
- 分散式鎖的實現原理分散式
- redis分散式鎖的實現Redis分散式
- 分散式鎖的實現方案分散式
- ZooKeeper分散式鎖的實現分散式
- etcd實現分散式鎖分散式
- 分散式鎖----Redis實現分散式Redis
- 分散式鎖及其實現分散式
- Redis實現分散式鎖Redis分散式
- 「分散式」實現分散式鎖的正確姿勢?!分散式
- 分散式鎖的實現及原理分散式
- redis實現分散式鎖---實操---問題解決Redis分散式
- 6 zookeeper實現分散式鎖分散式
- redis分散式鎖-java實現Redis分散式Java
- Redis之分散式鎖實現Redis分散式
- Elasticsearch系列---實現分散式鎖Elasticsearch分散式
- Redisson實現分散式鎖---原理Redis分散式
- Redisson實現分散式鎖—RedissonLockRedis分散式
- Redis如何實現分散式鎖Redis分散式
- 分散式鎖之Zookeeper實現分散式
- 分散式鎖之Redis實現分散式Redis
- 利用Redis實現分散式鎖Redis分散式
- 分散式鎖實現(二):Zookeeper分散式
- redis分散式鎖-SETNX實現Redis分散式
- 分散式鎖實現(一):Redis分散式Redis