Air433 / dddbook

spring boot 领域驱动设计Demo
435 stars 235 forks source link

同时有两个人转钱给我的并发问题,如何解决? #3

Open nogeek-cn opened 3 months ago

nogeek-cn commented 3 months ago
@Service
public class TransferServiceImpl implements TransferService {

    @Autowired
    private AccountRepository accountRepository;

    private AuditMessageProducer auditMessageProducer;
    private ExchangeRateService exchangeRateService;
    private AccountTransferService accountTransferService;

//    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result<Boolean> transfer(Long sourceUserId, String targetAccountNumber, BigDecimal targetAmount, String targetCurrency) throws Exception, DailyLimitExceededException {
        Money targetMoney = new Money(targetAmount, new Currency(targetCurrency));

        Account sourceAccount = accountRepository.find(new UserId(sourceUserId));

        Account targetAccount = accountRepository.find(new AccountNumber(targetAccountNumber));

        ExchangeRate exchangeRate = exchangeRateService.getExchangeRate(sourceAccount.getCurrency(), targetMoney.getCurrency());

        accountTransferService.transfer(sourceAccount, targetAccount, targetMoney, exchangeRate);

        accountRepository.save(sourceAccount);

        accountRepository.save(targetAccount);

        // 发送审计消息
        AuditMessage message = new AuditMessage(sourceAccount, targetAccount, targetMoney);
        auditMessageProducer.send(message);

        return Result.success(true);
    }
}

accountRepository.save(sourceAccount); accountRepository.save(targetAccount);

这一步的保存的并发问题怎么处理。比如,同时有两个人转钱给我的并发问题,如何解决?

Air433 commented 3 months ago

1.数据库层面可以使用乐观锁、悲观锁 2.分布式锁

nogeek-cn commented 3 months ago

如果数据库层面用乐观锁, 你看下你写的代码,领域模型怎么改动呢?

Air433 commented 3 months ago

在表里面加上版本号字段,更新的时候where条件加上版本号