我想以原子方式更新记录以保持一致性,可以使用以下SQL轻松完成。
UPDATE account SET balance = balance - 25 WHERE id = '5' AND balance > 25
或NoSQL(MongoDB)
db.account.update({_id: 5, balance: {$gte: 5}}, {$inc: {balance: -5}})
但在DDD中,如何在没有竞争条件的情况下正确地做到这一点?这应该很快,所以应该避免明确的锁定。 (除非DDD不可避免。)
可能会出现种族情况
class ApplicationService
func creditAccount(String accountId, int amount)
let account = accountRepository.find(accountId)
account.credit(amount)
accountRepository.save(account)
双重发送?
class ApplicationService
func creditAccount(String accountId, int amount)
let account = accountRepository.find(accountId)
account.credit(amount, accountDao)
class Account
func credit(int amount, AccountDao dao)
this.balance = dao.adjustAmountAndReturn(this.id, -amount)
修改的
我知道竞争条件的风险很低,但损失很大,因此成本乘以成本仍然会产生很高的预期值。
在这个问题中,我正在寻找一种适合RDBMS和NoSQL的解决方案。
答案 0 :(得分:1)
我认为您可以使用该查询实现域服务,如:
interface CreditAccountService {
void operation(String accountId, int amount);
}
class DbCreditAccountService implements CreditAccountService{
void operation(String accountId, int amount){
db.executeQuery("UPDATE account SET balance = balance - "+amount+" WHERE id = '"+accountId+"' AND balance > " + amount);
}
}
但也许使用锁定机制更好地管理竞争条件
如果您的应用程序根本没有分配,那么使用实体ID进行悲观锁定就足以防止竞争条件......
如果您的应用程序被复制到' n'服务器并且具有一致的数据库,您可以在db表中使用乐观锁
或者也许是分布式锁定,如果您的数据库是分布式的并且最终是一致的。
您可以获得有关悲观/乐观锁定here
的更多信息