Easily complete a distributed transaction TCC, nanny level tutorial with python

Posted by chris_s_22 on Sun, 16 Jan 2022 23:42:18 +0100

What is distributed transaction? Inter bank transfer business is A typical distributed transaction scenario. Assuming that A needs inter-bank transfer to B, the data of two banks are involved. The ACID of transfer cannot be guaranteed through the local transaction of one database, but can only be solved through distributed transactions.

Distributed transaction means that the initiator, resource manager and transaction coordinator of the transaction are located on different nodes of the distributed system. In the above transfer business, user A-100 operation and user B+100 operation are not located on the same node. In essence, distributed transaction is to ensure the correct execution of data operations in distributed scenarios.

What is TCC distributed transaction? TCC is the abbreviation of Try, Confirm and Cancel. It was first proposed by a paper entitled Life beyond Distributed Transactions:an Apostate's Opinion published by Pat Helland in 2007.

TCC composition

TCC is divided into three stages

  • Try phase: try to execute, complete all business checks (consistency), and reserve necessary business resources (quasi isolation)
  • Confirm phase: if the Try of all branches is successful, go to the confirm phase. Confirm really executes the business without any business check, and only uses the business resources reserved in the Try phase
  • Cancel phase: if one Try of all branches fails, go to the cancel phase. Cancel releases the business resources reserved in the Try phase.

There are three roles in TCC distributed transactions, which are the same as the classic XA distributed transactions:

  • The AP / application initiates a global transaction and defines which transaction branches are included in the global transaction
  • RM / resource manager is responsible for the management of various resources in branch transactions
  • TM / transaction manager is responsible for coordinating the correct execution of global transactions, including the execution of Confirm and Cancel, and handling network exceptions

If we want to conduct a business similar to inter-bank transfer, the transfer out and transfer in are in different micro services respectively. The typical sequence diagram of a successfully completed TCC transaction is as follows:

TCC network exception

During the whole process of global transactions, various network exceptions may occur in TCC, such as null rollback, idempotent and suspension. Because the exceptions of TCC are similar to SAGA, reliable message and other transaction modes, we put all the solutions to exceptions in this article Are you still troubled by the network anomaly of distributed transactions? A function call helps you handle it Explain

TCC practice

Let's develop a TCC transaction

At present, the open source framework available for TCC is mainly Java language, with seata as the representative. Our example uses python and the distributed transaction framework is dtm , its support for distributed transactions is elegant. Let's explain the composition of TCC in detail

Let's write a specific Try/Confirm/Cancel processing function

@app.post("/api/TransOutTry")
def trans_out_try():
    return {"result": "SUCCESS"}

@app.post("/api/TransOutConfirm")
def trans_out_confirm():
    return {"result": "SUCCESS"}

@app.post("/api/TransOutCancel")
def trans_out_cancel():
    return {"result": "SUCCESS"}

@app.post("/api/TransInTry")
def trans_in_try():
    return {"result": "SUCCESS"}

@app.post("/api/TransInConfirm")
def trans_in_confirm():
    return {"result": "SUCCESS"}

@app.post("/api/TransInCancel")
def trans_in_cancel():
    return {"result": "SUCCESS"}

At this point, the processing functions of each sub transaction are OK, and then start the TCC transaction for branch calls

# This is the dtm service address
dtm = "http://localhost:8080/api/dtmsvr"
# This is the business microservice address
svc = "http://localhost:5000/api"

@app.get("/api/fireTcc")
def fire_tcc():
    # Initiate tcc transaction
    gid = tcc.tcc_global_transaction(dtm, tcc_trans)
    return {"gid": gid}

# Specific processing of tcc transactions
def tcc_trans(t):
    req = {"amount": 30} # Load of service request
    # Call Try|Confirm|Cancel of the transfer out service
    t.call_branch(req, svc + "/TransOutTry", svc + "/TransOutConfirm", svc + "/TransOutCancel")
    # Call Try|Confirm|Cancel transferred into the service
    t.call_branch(req, svc + "/TransInTry", svc + "/TransInConfirm", svc + "/TransInCancel")

So far, a complete TCC distributed transaction is written.

If you want to run a successful example completely, refer to this example yedf/dtmcli-node-sample , it's very simple to run

# Deploy start dtm
# docker version 18 or above is required
git clone https://github.com/yedf/dtm
cd dtm
docker-compose up

# Start another command line
git clone https://github.com/yedf/dtmcli-py-sample
cd dtmcli-cli-sample
pip3 install flask dtmcli requests
flask run

# Start another command line
curl localhost:5000/api/fireTcc

Rollback of TCC

What if the bank finds that the account of user 2 is abnormal and fails to return when it is ready to transfer the amount to user 2? We give the sequence diagram of transaction failure interaction

The difference between this and a successful TCC is that when a sub transaction returns a failure, the global transaction is subsequently rolled back and the Cancel operation of each sub transaction is called to ensure that all global transactions are rolled back.

Summary

In this article, we introduce the theoretical knowledge of TCC, and give a complete process of writing a TCC transaction through an example, including normal successful completion and successful rollback. I believe readers have a deep understanding of TCC through this article.

After reading this article, welcome to visit dtm Project, give star support!
github.com/yedf/dtm

For idempotent, dangling and null compensation to be handled in distributed transactions, please refer to another article:

Distributed transaction you can not know the pit, a function call to help you handle it

If you are using go, you can visit dtm , there are examples of go running tcc

If you are using node, you can access yedf/dtmcli-node-sample , there are examples of node running tcc

Topics: Python