高并发锁事务重试机制(JPA高并发下的乐观锁异常)

乐观锁:

model实体类加version字段

 


    @JsonProperty("_version")
    @Column(name = "version", nullable = false)
    @Version
    private Long version = 0L;

 

 

问题场景

 先在库里查询出该实体,转化为持久态,在这时库里的该数据被修改了,并且version发生变更,此时持久态实体进行save操作,会触发乐观锁异常。

 

1:解决方案

     定义Aspectj拦截器,指定方法发生乐观锁异常时,进行重试。

 

2:show coding.

 

(1) 因为不是所有方法发生乐观锁异常都是需要重试机制的,所以需要先定义切面接口定义IsTryAgain

/** 
 * 自定义尝试切面接口 
 */  
@Retention(RetentionPolicy.RUNTIME)  
public @interface IsTryAgain {  
    // marker annotation  
}  

 (2)Service接口方法加上切面接口定义

/** 
 * 并发乐观锁需要重试的方法 
 */  
@IsTryAgain  
boolean TryAgainMethod() throws Exception;  

(3)定义Aspectj切面拦截器

 

定义重试切面方法,是为了发生乐观锁异常时在一个全新的事务里提交上一次的操作,直到达到重试上限;因此切面实现 org.springframework.core.Ordered 接口,这样我们就可以把切面的优先级设定为高于事务通知 。

@Aspect  
public class SystemArchitecture {  
      
    @Pointcut("execution(* myapp..service..*(..))")  
    public void businessService() {  
    }  
      
}  
@Aspect   
class ConcurrentOperationExecutor implements Ordered {  
     
   private static final int DEFAULT_MAX_RETRIES = 2;  
  
   private int maxRetries = DEFAULT_MAX_RETRIES;  
   private int order = 1;  
  
   public void setMaxRetries(int maxRetries) {  
      this.maxRetries = maxRetries;  
   }  
     
   public int getOrder() {  
      return this.order;  
   }  
     
   @Around("myapp.SystemArchitecture.businessService()")  
   public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {   
      int numAttempts = 0;  
      PessimisticLockingFailureException lockFailureException;  
      do {  
         numAttempts++;  
         try {   
            return pjp.proceed();  
         }  
         catch(PessimisticLockingFailureException ex) {  
            lockFailureException = ex;  
         }  
      }while(numAttempts <= this.maxRetries);  
  
        
      throw lockFailureException;  
   }  
  
}  

 3:更多

AOP知识,Spring AOP和Aspectj的知识。

你可能感兴趣的:(基础框架)