如图所示,bool withdraw(account_id, amount)函数表示:从account_id对应的账户中扣除amount数额的钱;如果扣除成功则返回true,账户余额减少amount;如果扣除失败则返回false,账户余额不变。
如果withdraw请求已经被服务器端正确处理,但服务器端的返回结果由于网络等原因被掉丢了,导致客户端无法得知处理结果。如果是在网页上,一些不恰当的设计可能会使用户认为上一次操作失败了,然后刷新页面,这就导致了withdraw被调用两次,账户也被多扣了一次钱。因此我们要做幂等控制。
问题:
如果采用采用分布式事务,通过引入支持分布式事务的中间件来保证withdraw功能的事务性,有哪些中间件可以提供这些功能?具体怎么实现的啊?
First of all, RocketMQ, Alibaba’s open source message middleware, was originally called MetaQ. The document states that it supports distributed transactions. Because all aspects of RocketMQ, including producers, consumers, and brokers, are distributed, it can basically be guaranteed. It was lost due to network reasons, but we did not use this feature in the project. Moreover, RocketMQ has the problem of repeated consumption, so the document clearly states that the business side should implement idempotence by themselves.
Secondly, I think that in most cases, distributed transactions are rarely implemented. In most cases, it is enough to ensure final consistency, and the performance of distributed transactions is low.
In addition, idempotent In fact, it has little to do with the distributed transactions you mentioned. In the same scenario, even if your systems are all together, what should you do if you receive two identical requests? If idempotence is not achieved, it is not a distributed scenario. There will also be more deductions.
And idempotence can be achieved by issuing tokens, etc. (there are actually many articles introduced)
First of all, this scenario has nothing to do with distributed transactions!
Secondly, regarding the idempotence of services, there are many ways to guarantee it. Specific to your scenario, you can define a request in the protocol to represent the requestID. On the server side, verify this requestID, such as using a simple redis distributed Lock or other distributed lock can be verified for idempotence
Involves failure retries, so the provider's interface must be idempotent. However, interfaces such as inventory deduction are difficult to achieve idempotence, so it is recommended to close the failed retry of the failed interface.
For the topic's scenario, the main reason is that the caller failed due to timeout and did not rollback
amount
, because my guess is correct, this should be an RPC call, so the topic really needs distributed transactions. To perform transaction rollback, you can refer to ByteTCC for details. Using TCC is also a solution