Wechat official account “Backend Advanced” focuses on back-end technology sharing: Java, Golang, WEB framework, distributed middleware, service governance and so on.

In the microservice architecture system, we can design according to the layers of business modules and deploy separately, which reduces the pressure of service deployment and decouples the business coupling, avoiding the application from gradually becoming a monster, so that it can be easily expanded, and the normal operation of other services will not be affected when some services fail. In short, the tiny segment business bring us more and more advantage in the high speed development, but the service is not perfect, so can’t blind excessive abuse, it has many defects, and can bring certain complexity to the system, the distributed transaction associated with problems, is the need to deal with micro service architecture system under a sore point, It is also an area of concern in the industry, hence the emergence of theories such as CAP and BASE.

At the beginning of this year, Ali opened source a distributed transaction middleware, originally named Fescar and later renamed Seata. At the beginning of its open source, I knew it would be popular, because it was an open source project to solve the pain point. Seata was aimed at non-intrusion into business and high performance at the beginning. This is the urgent need to solve the distributed transaction problem. Stayed for several companies, using all of these micro service architecture, but on solve the problem of distributed transactions are not very elegant, so I has been paying attention to the development of Seata, today just briefly tell me about it in the design of the principle, the subsequent I will its various modules for in-depth analysis of source code, interested can continuous attention to the public, or my blog, Don’t lose him.

What are the solutions for distributed transaction solutions?

At present, the solutions of distributed transaction mainly include invasion-free and invasion-free schemes. The invasion-free schemes mainly include two-stage commit (2PC) scheme based on DATABASE XA protocol, which has the advantage of invasion-free to business code, but its disadvantages are also obvious: The database must be required to support XA protocol, and because of the characteristics of XA protocol itself, it will cause transaction resources not released for a long time, long lock cycle, and can not be interfered in the application layer, so its performance is very poor, its existence is equivalent to the “seven hurt fist”, “hurt seven points, hurt oneself three points”. Therefore, this solution is not very popular in Internet projects.

In order to make up for the problem of low performance brought by such a scheme, big men have come up with many solutions to solve it, but all of them need to manipulate the application layer, that is, invade the business, such as the famous TCC scheme, there are many mature frameworks based on TCC. For example, ByteTCC and TCC-Transaction. And ultimate consistency based on reliable messages, such as RocketMQ’s transaction messages.

Invasion of the code solution was introduced based on existing situation “forced” to the solution of, in fact they implement very not elegant, usually accompanied by a transaction calls is to increase the transaction interface series of reverse operation, such as TCC three-step submitted, submitted logic inevitably accompanied by a rollback logic, this code will make the project very bloated, High maintenance costs.

Relationships between modules in Seata

Distributed transaction solution for above pain points, then, obviously our ideal solution for distributed transactions must be better performance and no invasion to the business, the business layer on the do not need to care about the constraint of the distributed transaction, Seata is toward this direction, so it is worth looking forward to, it will bring to our micro service architecture quality.

So how does Seata do it? Here’s how its modules relate to each other.

Seata is designed to think of a distributed transaction as a global transaction, with several branch transactions hanging from it, and a branch transaction being a local transaction that meets ACID, so we can operate a distributed transaction as if it were a local transaction.

Seata internally defines three modules to handle the relationship and processing of global and branch transactions. These three components are:

  • Transaction Coordinator (TC) : A Transaction Coordinator that maintains the running status of global transactions and coordinates and drives the commit or rollback of global transactions.
  • Transaction Manager (TM) : Controls the boundaries of a global Transaction, is responsible for starting a global Transaction, and ultimately initiating a global commit or rollback resolution.
  • Resource Manager (RM) : Controls branch transactions, is responsible for branch registration, status reporting, receives transaction coordinator instructions, and drives the commit and rollback of branch (local) transactions.

A brief description of the overall global transaction execution steps:

  1. TM applies to TC for starting a global transaction. After TC creates a global transaction, it returns the globally unique XID, which will be propagated in the context of the global transaction.
  2. RM registers branch transactions with TC. The branch transactions belong to global transactions with the same XID.
  3. TM initiates global commit or rollback to TC;
  4. TC schedules branch transactions under XID to commit or roll back.

How is it different from the XA scheme?

Seata’s transaction commits are generally the same as XA’s two-part commits. What’s the difference?

As we all know, XA protocol relies on the database level to guarantee the consistency of transactions, that is, each branch transaction of XA is driven at the database level. Since each branch transaction of XA requires XA drivers, on the one hand, database and XA driver will be coupled. On the other hand, it will lead to long transaction resource lock cycle of each branch, which is also an important factor that it is not popular in Internet companies.

Based on the XA protocol above, Seata takes a different approach. Since there are so many problems caused by relying on the database layer, I will start with the application layer. This also starts from the RM module of Seata, which also mentioned the main function of RM.

Seata does a proxy layer on the data source, so when we use Seata, the data source is actually Seata’s own DataSourceProxy, DataSourceProxy, Seata adds a lot of logic to this proxy, mainly parsing SQL, The data mirroring before and after the service data update is organized into rollback logs, and the undo log is inserted into the undo_log table to ensure that each service SQL that updates data has a corresponding rollback log.

In this way, the resources locked by the local transaction can be released immediately after the local transaction is executed, and the branch status can be reported to the TC. When TM decides global submission, there is no need for synchronous coordination, TC will asynchronously schedule each RM branch transaction to delete the corresponding Undo log, and this step can be completed very quickly. When TM decides to roll back globally, RM receives the rollback request from TC. RM uses XID to find the corresponding undo log and executes the rollback log to complete the rollback.

As shown in the figure above, the RM of the XA schema is placed in the database layer and relies on the XA driver of the database.

As shown in the figure above, THE RM of Seata is actually placed in the application layer in the form of middleware, and does not rely on the support of the database for the protocol, completely stripping the requirements of the distributed transaction scheme on the support of the database for the protocol.

How are branch transactions committed and rolled back?

Here’s how branch transactions are committed and rolled back:

  • Stage 1:

Branch transaction uses RM module to JDBC data source agent, adds a number of processes, explains the business SQL, organizes the data mirror before and after the update of the business data into rollback log, generates undo log, checks the global transaction lock and registers branch transactions, etc. Using the local transaction ACID feature, the service SQL and undo log are written into the same thing and submitted to the database together to ensure that the service SQL must have corresponding rollback logs. Finally, the status of branch transactions is reported to the TC.

  • Stage 2:

TM Resolution global submission:

When TM resolution is submitted, there is no need for synchronous coordination processing, TC will asynchronously schedule each RM branch transaction to delete the corresponding undo log, and this step can be completed very quickly. This mechanism is very important for improving performance. We know that the success rate of transaction execution is very high in normal business operation, so it can be committed directly in local transaction, which can improve performance significantly.

TM resolution global rollback:

When TM decides to roll back, RM receives the rollback request from TC, finds the corresponding undo log through XID, executes the rollback log to complete the rollback and delete the undo log using the local transaction ACID feature, and reports the rollback result to TC.

The business is not aware of any of the above processes, the business is not concerned with the specific commit and rollback of the global transaction, and most importantly, Seata breaks the synchronization coordination of the two-phase commit into branch transactions. Branch transactions are no different from ordinary local transactions, which means that when we use Seata, Like using local transaction, distributed transaction completely transfers transaction coordination mechanism of database layer to middleware layer Seata. In this way, although transaction coordination is moved to application layer, it can still achieve zero intrusion to business, thus stripping the requirement of distributed transaction scheme on protocol support of database. Moreover, Seata directly releases resources after the completion of branch transactions, which greatly reduces the locking time of resources by branch transactions and perfectly avoids the problem of resource locking time caused by XA protocol synchronization coordination.

Supplement to other programs

Seata’s default mode, also called AT mode, is a two-stage commit scheme similar to XA scheme, and is non-intrusive to business. However, this mechanism still depends on the ACID characteristics of database local transactions. Have you noticed that, The problem is that databases that are not relational or do not support ACID cannot use Seata. Do not panic. Seata currently has another schema for us, called MT schema, which is a business-intrusive solution. Operations such as Commit Rollback need to be defined by ourselves. The business logic needs to be decomposed into Prepare, Commit and Rollback parts to form an MT branch and join in the global transaction. The purpose of this branch is to reach more scenarios for Seata.

However, it is not Seata’s “main” model, it exists only as a complementary solution, as can be seen from the above official development vision, Seata’s goal is always to be a business-free solution.

Note: The graphic design of this article refers to the official Seata chart