@
lujiaxing 我之前就是这么实现的,然后忘记出现了高并发频繁事务失败还是余额加错的问题,代码大致是这样的
var strategy = dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
using (var transaction = await dbContext.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted))
{
var user = await dbContext.Users.NotCacheable().FirstOrDefaultAsync(x => x.UserId == userId);
if (user == null) return;
await dbContext.Entry(user).ReloadAsync();
if (balanceChange < 0 && user.Balance < balanceChange * -1) throw new Exception("UserBalanceNotEnough");
await dbContext.Database.ExecuteSqlRawAsync(
"UPDATE Users SET Balance = Balance + {0} WHERE UserId = {1}",
new object[] { balanceChange, userId });
var balanceRecord = new BalanceRecord
{
UserId = userId,
Description = description,
OperatorIp = operatorIp,
BalanceChange = balanceChange,
RemainingBalance = user.Balance + balanceChange
};
await dbContext.BalanceRecords.AddAsync(balanceRecord);
try
{
await dbContext.SaveChangesAsync();
await transaction.CommitAsync();
}
catch (Exception ex)
{
await transaction.RollbackAsync();
}
}
}
改了好几个版本,最后只能又套了一个 Redis 锁,但是会导致高并发性能变差很多