In previous articles, we introduced the concept of distributed transactions and some of the solutions. FenSeata is an open source distributed transaction solution dedicated to providing high performance and easy to use distributed transaction services. Seata will provide users with AT, TCC, SAGA and XA transaction modes to create a one-stop distributed solution for users.

Introduce Seata

This article introduces the principle and use of open source framework Seata by taking a system where users place orders for goods as an example. The system involves three parts of services:

  1. Storage service: deduct the storage quantity for a given commodity;
  2. Order service: create orders according to purchasing requirements;
  3. Account services: deduct balances from user accounts;

The main function of distributed transaction is to ensure the consistency of data in the process of user ordering in microservices. Consistency here can be understood as follows: there is no scenario where the user balance deduction succeeds, but warehousing and order-related operations fail, and all three succeed or fail at the same time.

Single machine transaction scenario

If the services involved in ordering and purchasing goods are all in a traditional stand-alone service, the three parts of the service can share the same database instance. In this case, we can ensure data consistency between warehouse/order/account through consistency of local transactions.

As shown in the figure above, in a standalone service, all three parts share the same database instance, so we only need local transactions to resolve data consistency. In the Spring framework, for example, we only need to add @Transaction annotations to the method to achieve data consistency throughout the purchase process:

@Transaction
public void purchase(a){
    doStoreBusiness();
    doOrderBusiness();
    doAccountBusiness();
}
Copy the code

Distributed transaction scenario

In the microservices framework, the warehouse/order/account services are deployed on different servers, using different database instances, and are completely different from the stand-alone mode. The transaction in single-machine mode usually requires that the data source involved in the transaction is the same, and the database operation involved in the transaction is in the same database link, which obviously does not meet the requirements in the distributed case.

So how do you ensure data consistency in distributed scenarios? This is the problem Seata needs to solve.

Seata solutions

Seata is an open source framework for solving distributed transactions. The internal definition of distributed transactions is as follows: DISTRIBUTED transactions are global transactions consisting of multiple branch transactions, each of which is in the form of a local transaction.

The Seata framework consists of three parts:

  1. Transaction Coordinator (TC) : Maintains the status of global and branch transactions, commits or rolls back global transactions.
  2. Transaction Manager (TM) : Defines, enables, commits, or rolls back global transactions;
  3. Resource Manager (RM) : Manages resources in branch transactions, registers branch transactions with the transaction Manager and reports the status of branch transactions, and is responsible for submitting or rolling back branch transactions;

A typical SeATA distributed transaction flows as follows:

  1. TM sends a request to TC to enable the global transaction, and TC generates the unique identifier XID of the global transaction. Set the global transaction here as T1.
  2. In the processes of global transaction T1, XIDS are used as transaction identifiers to flow between microservices.
  3. RM registers local transactions with TC. The registered local transactions are regarded as branch transactions of global transaction T1.
  4. TM can request TC to control global transaction T1 commit or rollback.
  5. TC can request all branch transactions under global transaction T1 to commit or roll back;

Seata history

Alibaba:

  • TXC: Distributed transaction framework of Taobao transaction system. Alibaba middleware team started this project in 2014, which is used to solve distributed transaction problems caused by the transformation of application architecture from single service to micro-service;
  • GTS: Global transaction services. TXC, as a middleware product of Alibaba Cloud, was released in 2016 under the new name OF GTS.
  • Fescar: Fescar, an open source project based on TXC/GTS, was started in 2019 for the development of the open source project community;

Ant Financial:

  • XTS: Extended transaction services. Ant Financial Middleware team has been developing distributed transaction middleware since 2007, which has been widely used in Ant Financial to solve the problem of data consistency across databases and services.
  • DTX: Distributed transaction extension. Since 2013, XTS has been released on Ant Financial Cloud under the name DTX;

Seata communities:

  • Seata: Simple scalable distributed transaction solution. Ant Financial renamed Fedscar as Seata and opened the source, making it a neutral and open distributed transaction community.

Seata Maven rely on

<seata.version>1.4.2</seata.version>

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-all</artifactId>
    <version>${seata.version}</version>
</dependency>
Copy the code

Seata case

As an example of how Seata can be used, see the above system for ordering goods:

  1. Warehouse micro service: deduct warehouse quantity for a given item;
  2. Order micro service: create orders according to purchase requirements;
  3. Account microservice: deduct the balance from the user account;

Definition of the service interface

For the three microservices, we use three interfaces to abstract the internal logic:

  • Warehousing services

    public interface StorageService {
    
          /** * deduct the number of storage */
          void deduct(String commodityCode, int count);
      }
    Copy the code
  • Order service

      public interface OrderService {
          /** * create order */
          Order create(String userId, String commodityCode, int orderCount);
      }
    Copy the code
  • Account service

    public interface AccountService {
    
        /** * lends */ from the user account
        void debit(String userId, int money);
    }
    Copy the code

Main business logic

For the logic of ordering and purchasing goods, we use the following code to achieve:

  • Main business logic

      public class BusinessServiceImpl implements BusinessService {
    
          private StorageService storageService;
    
          private OrderService orderService;
    
          /** ** ** */
          public void purchase(String userId, String commodityCode, int orderCount) { storageService.deduct(commodityCode, orderCount); orderService.create(userId, commodityCode, orderCount); }}Copy the code
  • Order service business logic

      public class OrderServiceImpl implements OrderService {
    
          private OrderDAO orderDAO;
    
          private AccountService accountService;
    
          public Order create(String userId, String commodityCode, int orderCount) {
    
              int orderMoney = calculate(commodityCode, orderCount);
    
              accountService.debit(userId, orderMoney);
    
              Order order = new Order();
              order.userId = userId;
              order.commodityCode = commodityCode;
              order.count = orderCount;
              order.money = orderMoney;
    
              // INSERT INTO orders ...
              returnorderDAO.insert(order); }}Copy the code

The introduction of Seata

After introducing the Seata service into the service, we simply need to add the distributed transaction annotation @GlobalTransactional on the outermost method of the distributed transaction:

@GlobalTransactional
public void purchase(String userId, String commodityCode, int orderCount) {
    / /...
}
Copy the code

After the annotations are added, Seata creates the global transaction ID before executing the business logic and carries the global transaction ID in the request when calling other services. If other microservices also add Seata dependencies, they get the global transaction ID and participate in the global transaction.

This article is a brief introduction to the following Seata framework, which will be described in more detail in a future article.

I am the god of the royal Fox. Welcome to follow my wechat official account: Wzm2ZSD

Reference documentation

Seata official documentation

This article was first published to wechat public account, all rights reserved, reprint prohibited!