场景
批量订单上传,循环遍历一个集合,然后存储其中的图片地址,并且改变其中订单状态。
问题
由于 Spring 注解 @Transactional 管理事务的时候,是在所以集合遍历结束以后才会提交事务,所以当我们给某个订单添加分布式锁的时候,如果这个时候当下订单业务逻辑完成释放了锁,数据库中的数据还是没有更新的,所以当有新的线程获取到锁判断订单状态的时候,这个时候订单仍然属于未上传的状态,所以会导致订单的重复上传。
解决办法
改为手动事务管理,当我们的某个订单上传成功以后,手动提交事务,然后再去释放分布式锁。
代码
public ResultV0 uploadOrder(List<UploadOrderRequest> requests) {
for (UploadOrderRequest request : requests) {
// 手动管理事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = txManager.getTransaction(def);
// 上锁
String key = "upload_order_" + request.getOrderSn();
RLock lock = redissonClient.getLock(key.intern());
try {
lock.lock();
/**
订单上传逻辑部分
**/
// 手动提交事务
txManager.commit(status);
} catch (Exception e) {
// 手动回滚事务
txManager.rollback(status);
} finally
{
lock.unlock();
}
}
return new ResultV0(ResultCode.SUCCESS);
}
总结
事务的提交时机,将会影响到分布式锁状态的判断。