Affairs
Certain business requirements require that a series of operations must be performed entirely, not just a part of it. For example, a transfer operation:
-- 从id=1的账户给id=2的账户转账100元
-- 第一步:将id=1的A账户余额减去100
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
-- 第二步:将id=2的B账户余额加上100
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
These two SQL statements must all be executed, or, for some reason, if the first statement succeeds and the second statement fails, all must be cancelled.
This function of operating multiple statements as a whole is called a database transaction. A database transaction can ensure that all operations within the scope of the transaction can all succeed or all fail. If the transaction fails, the effect is the same as if these SQLs are not executed, and there will be no changes to the database data.
Microservice
If all operations involved in a transaction can be placed inside a service, then using transaction-related libraries in each language can easily implement multiple operations as a whole transaction operation.
But some services, such as generating orders, involve many operations, including inventory, coupons, gifts, account balances, etc. When the complexity of the system increases, if you want to implement all these operations in one service, the coupling will be too high and the maintenance cost will be very high.
For complex systems, the current popular microservice architecture is a very good solution. This architecture can split the complex system and form a large number of microservices after the split, which is independently developed and maintained.
Although the service is split, the logic of the order itself requires multiple operations as a whole, either all succeed or all fail, which brings new challenges. How to combine the local transactions scattered in various microservices into a large transaction to ensure that they are as a whole, this is the problem that distributed transactions need to solve.
Distributed transaction
Distributed transaction simply means that a large operation is composed of different small operations. These small operations are distributed on different servers and belong to different applications. Distributed transactions need to ensure that these small operations are either all successful or all fail. Essentially, distributed transactions are to ensure data consistency in different databases.
More distributed transaction introduction
Distributed transaction solutions include:
- xa
- tcc
- saga
- Reliable news
Let's take a look at the simplest xa
XA
XA is a specification for distributed transactions proposed by the X/Open organization. The XA specification mainly defines the interface between the (global) transaction manager (TM) and the (local) resource manager (RM). Local databases such as mysql play the role of RM in XA
XA is divided into two stages:
The first stage (prepare): That is, all participants RM prepare to execute the transaction and lock the required resources. When the participant is ready, report to TM that it is ready.
The second stage (commit/rollback): When the transaction manager (TM) confirms that all participants (RM) are ready, send a commit command to all participants.
At present, mainstream databases basically support XA transactions, including mysql, oracle, sqlserver, and postgre
Let's see how the local database supports XA:
First stage preparation
XA start '4fPqCNTYeSG'
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG'
-- 当所有的参与者完成了prepare,就进入第二阶段 提交
xa commit '4fPqCNTYeSG'
xa practice
Introduced so much, let's practice to complete the xa transaction on a microservice and deepen the understanding of distributed transactions. Here we use dtm as the manager of distributed transactions to run one of the xa demos.
Get dtm
git clone https://github.com/yedf/dtm.git
cd dtm
Configure mysql
cp conf.sample.yml conf.yml
vi conf.yml
Run example
go run app/main.go xa
From the log, the output of the XA part can be found, and finally the transaction is successfully submitted and completed
# 服务1输出
XA start '4fPqCNTYeSG'
UPDATE `user_account` SET `balance`=balance - 30,`update_time`='2021-06-09 11:50:42.438' WHERE user_id = '1'
XA end '4fPqCNTYeSG'
XA prepare '4fPqCNTYeSG'
# 服务2输出
XA start '4fPqCPijxyC'
UPDATE `user_account` SET `balance`=balance + 30,`update_time`='2021-06-09 11:50:42.493' WHERE user_id = '2'
XA end '4fPqCPijxyC'
XA prepare '4fPqCPijxyC'
# 服务1输出
xa commit '4fPqCNTYeSG'
#服务2输出
xa commit '4fPqCPijxyC'
The timing details of the entire interaction are as follows
code show as below:
// 微服务的处理函数:
app.POST(BusiAPI+"/TransInXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) {
return XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) (interface{}, error) {
_, err := dtmcli.DBExec(db, "update dtm_busi.user_account set balance=balance+? where user_id=?", reqFrom(c).Amount, 2)
return dtmcli.MapSuccess, err
})
}))
app.POST(BusiAPI+"/TransOutXa", common.WrapHandler(func(c *gin.Context) (interface{}, error) {
return XaClient.XaLocalTransaction(c.Request.URL.Query(), func(db *sql.DB, xa *dtmcli.Xa) (interface{}, error) {
_, err := dtmcli.DBExec(db, "update dtm_busi.user_account set balance=balance-? where user_id=?", reqFrom(c).Amount, 1)
return dtmcli.MapSuccess, err
})
}))
// 开启XA事务
err := XaClient.XaGlobalTransaction(gid, func(xa *dtmcli.Xa) (*resty.Response, error) {
resp, err := xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransOutXa")
if err != nil {
return resp, err
}
return xa.CallBranch(&TransReq{Amount: 30}, Busi+"/TransInXa")
})
Summarize
At this point, a complete introduction to xa distributed transactions is complete.
For more comprehensive knowledge of most classic seven solutions for distributed transactions
In this short article, we briefly introduced transactions, distributed transactions, and microservices processing XA transactions. Interested students can continue to study distributed transactions dtm
If you think the article is useful to you, welcome everyone to visit the https://github.com/yedf/dtm project, give star support!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。