String url = "http://localhost:8888/catalogRetry";
for(int i = 0; i < 100; i++) {
final int num = i;
new Thread(() -> {
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("catalogId", "1");
params.add("user", "user" + num);
String result = testRestTemplate.postForObject(url, params, String.class);
System.out.println("-------------" + result);
}
).start();
}
}
}
调用100次,即一个商品可以浏览一百次,采用悲观锁,catalog表的数据都是100,并且browse表也是100条记录 。采用乐观锁的时候,因为版本号的匹配关系,那么会有一些记录丢失,但是这两个表的数据是可以对应上的 。
乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,下面我就自定义了一个注解,用于做切面 。
package com.hqs.dblock.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RetryOnFailure {
}
针对注解进行切面,见如下代码 。我设置了最大重试次数5,然后超过5次后就不再重试 。
package com.hqs.dblock.aspect;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.StaleObjectStateException;
import org.springframework.orm.ObjectOptimisticLockingFailureException;
import org.springframework.stereotype.Component;
@Slf4j
@Aspect
@Component
public class RetryAspect {
public static final int MAX_RETRY_TIMES = 5;//max retry times
@Pointcut("@annotation(com.hqs.dblock.annotation.RetryOnFailure)") //self-defined pointcount for RetryOnFailure
public void retryOnFailure(){}
@Around("retryOnFailure()") //around can be execute before and after the point
public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable {
int attempts = 0;
do {
attempts++;
try {
pjp.proceed();
} catch (Exception e) {
if(e instanceof ObjectOptimisticLockingFailureException ||
e instanceof StaleObjectStateException) {
log.info("retrying....times:{}", attempts);
if(attempts > MAX_RETRY_TIMES) {
log.info("retry excceed the max times..");
throw e;
}
}
}
} while (attempts < MAX_RETRY_TIMES);
return null;
}
}
大致思路是这样了 。
【解决并发问题,数据库常用的两把锁!】
推荐阅读
- 企业常见5大网络安全问题
- 防御DDoS攻击需要双向解决方案
- Redis 这么火,它都解决了哪些问题?
- 双网卡网络时断时续解决方法
- 化妆品|美容行业九大痛苦现状,如何解决生存之道?
- 离婚前必须清楚的十大问题
- 3招解决安卓机卡慢
- 微信消息延迟不提醒?原来是这2个原因导致的,一招教你解决
- 淘宝违规被限制登录怎么办?限制登录的解决办法 淘宝被限制登录怎么办?限制登录的解决办法
- 手机已连接WiFi但无法访问互联网,是什么问题?
