福田建设网站,做网站准备什么问题,2022网络游戏排行榜前十名,西安seo外包优化一、前言
平时使用切面去加分布式锁#xff0c;是先开启事务还是先尝试获得锁#xff1f;这两者有啥区别#xff1f;
业务中怎么控制切面的顺序#xff1f;切面的顺序对事务的影响怎么避免#xff1f;
下面程序分析#xff1a; OverrideTransactionalpublic ReceiveH5…一、前言
平时使用切面去加分布式锁是先开启事务还是先尝试获得锁这两者有啥区别
业务中怎么控制切面的顺序切面的顺序对事务的影响怎么避免
下面程序分析 OverrideTransactionalpublic ReceiveH5ActivityPrizeResponse receive(ReceiveH5ActivityPrizeRequest request) {logger.info(xxx:{}, JSON.toJSONString(request));ReceiveH5ActivityPrizeResponse responsenew ReceiveH5ActivityPrizeResponse();String lockNamereceiveH5ActivityPrize request.getActivityId();final DistributeLock lock jedisLockFactory.getJedisLock(lockName,20, TimeUnit.SECONDS);// 1.加锁lock.lock();try {//todo // 2 业务逻辑 先判断是否存在不存在插入一条数据存在返回(不插入)} finally {// 3.释放锁lock.unLock();}// 4 返回return response;}
分布式锁失效并不是真正的失效只是读到数据读取的数据库数据不是最新的。
Transactional 注解在执行该方法时开启一个事物当执行到3步时insert 事物务还未提交因此其它线程进入分布式锁代码块后继续会执行2操作发现数据不存在继续插入一条新数据存在两条记录此时数据就会出现 bug 问题。
解决办法先加锁然后在开启事物可以保证安全性。
二、普通未指定 order 的切面和 Transactional 的先后顺序 先说下为啥会考虑到这个我们可以知道 Transaction 一般加在具体要执行业务的service 方法上那如果我要进行并发控制对业务进行加锁那么尝试锁和开启事务孰先孰后呢 OverrideTransactionalRedisLock(key Constant.FANLI_GRANT_VIP_LOCK, param #vipOrderNo)public void grantGdVip(String vipOrderNo) {// 业务逻辑} 按照业务流程上来看我们需要先尝试锁后开启事务因为没获得锁开启事务需要和数据库进行交互开启一个新的事务平常对业务结果是不会影响的但是当高并发时是会对数据库带来不小压力。
总结 如果普通切面没指定 order 会比 transaction 后执行。当锁或者一些检查性切面被使用时如果条件不满足不能进入业务也会导致事务的开启产生了不必要的消耗当并发高时尤为明显。
三、切面的顺序对事务的影响怎么避免
其实避免方式有三种一种是指定order一种是把自定义切面移到更外层中一种是使用编程式事务。
1、指定 Order
Aspect
Component
Slf4j
Order(1)
public class LockAspect {}
2、移到最外层中
移到更外层中就不用证明了调用的自然顺序比如放在Controller的方法上。 PostMapping(/web/cardb/gift/receive)ApiOperation(B卡赠品领取接口)TokenAuthenticationRedisLock(key LockKey.RECEIVE_CARD_B_GIFT, param #userInfo.userId)public ApiResultResponse receiveCardBGift(RequestBody Valid CardbReceiveGiftRequest request) {// 代码
}
3、使用编程式事务 当然可以调用的自然顺序事务的开启更加现式。
四、总结
因为声明式事务比较好用生产中使用的比较多只有为了控制事务粒度或者不需要抽出一个新的类为了使事务生效才会使用编程式事务。
所以更加倾向于移到更外层因为指定 order 的前提是你知道事务切面的和不指定order普通切面的顺序同时一旦切面变多比如有统一加锁切面、统一检查是否认证切面等需要控制自定义切面顺序容易和事务切面搞混不利于维护这个也相当于自定义切面和框架前面隔离。这也从一个侧面证明了校验放 controller 的合理性。
五、参考文档
Transactional和普通自定义切面执行顺序的思考