Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transfer-tcc-sample 子项目中 冻结金额的操作是不是多余的 #615

Open
HE996 opened this issue May 5, 2023 · 6 comments
Open

Comments

@HE996
Copy link

HE996 commented May 5, 2023

public boolean prepareMinus(BusinessActionContext businessActionContext, final String accountNo,
                                final double amount) {
        //分布式事务ID
        final String xid = businessActionContext.getXid();

        return fromDsTransactionTemplate.execute(new TransactionCallback<Boolean>() {

            @Override
            public Boolean doInTransaction(TransactionStatus status) {
                try {
                    //校验账户余额
                    Account account = fromAccountDAO.getAccountForUpdate(accountNo);
                    if (account == null) {
                        throw new RuntimeException("账户不存在");
                    }
                    if (account.getAmount() - amount < 0) {
                        throw new RuntimeException("余额不足");
                    }
                    //冻结转账金额
                    double freezedAmount = account.getFreezedAmount() + amount;
                    account.setFreezedAmount(freezedAmount);
                    fromAccountDAO.updateFreezedAmount(account);
                    System.out.println(String
                        .format("prepareMinus account[%s] amount[%f], dtx transaction id: %s.", accountNo, amount,
                            xid));
                    return true;
                } catch (Throwable t) {
                    t.printStackTrace();
                    status.setRollbackOnly();
                    return false;
                }
            }
        });
    }

这段代码中对FreezedAmount的操作有何意义?

@funky-eyes
Copy link
Contributor

想想不冻结如果再来一个扣款会发生什么?如果要回滚又如何回滚?要回滚多少金额?用户看到账户的金额又是多少?

@HE996
Copy link
Author

HE996 commented May 5, 2023

你好,

if (account.getAmount() - amount < 0) {
throw new RuntimeException("余额不足");
}

这里应该是

if (account.getAmount() - account.getFreezedAmount()< amount  {
throw new RuntimeException("余额不足");
}

@HE996
Copy link
Author

HE996 commented May 5, 2023

分布式事务有哪些书籍可以推荐呀或者开源项目做做参考

@slievrly
Copy link
Member

slievrly commented May 6, 2023

getAccountForUpdate

你的逻辑是对的。

@L1uxiaolin
Copy link

public boolean prepareMinus(BusinessActionContext businessActionContext, final String accountNo,
                                final double amount) {
        //分布式事务ID
        final String xid = businessActionContext.getXid();

        return fromDsTransactionTemplate.execute(new TransactionCallback<Boolean>() {

            @Override
            public Boolean doInTransaction(TransactionStatus status) {
                try {
                    //校验账户余额
                    Account account = fromAccountDAO.getAccountForUpdate(accountNo);
                    if (account == null) {
                        throw new RuntimeException("账户不存在");
                    }
                    if (account.getAmount() - amount < 0) {
                        throw new RuntimeException("余额不足");
                    }
                    //冻结转账金额
                    double freezedAmount = account.getFreezedAmount() + amount;
                    account.setFreezedAmount(freezedAmount);
                    fromAccountDAO.updateFreezedAmount(account);
                    System.out.println(String
                        .format("prepareMinus account[%s] amount[%f], dtx transaction id: %s.", accountNo, amount,
                            xid));
                    return true;
                } catch (Throwable t) {
                    t.printStackTrace();
                    status.setRollbackOnly();
                    return false;
                }
            }
        });
    }

这段代码中对FreezedAmount的操作有何意义?

不冻结的话,可能存在超出余额的转账事务存在。比如余额是100,A事务转50,B事务转100,这个时候B事务只会看到余额有100,不清楚其他事务是否也在转账中。加上第二阶段又必须成功,会导致两笔都成功。

@L1uxiaolin
Copy link

L1uxiaolin commented Mar 30, 2024

你好,

if (account.getAmount() - amount < 0) {
throw new RuntimeException("余额不足");
}

这里应该是

if (account.getAmount() - account.getFreezedAmount()< amount  {
throw new RuntimeException("余额不足");
}

你没理解冻结的概念,冻结的意思是这部分钱被某个事务占用了,并且已经从余额里扣除了,就不用再参与其他事务的计算了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants