SoFunction
Updated on 2024-07-16

Springcloud seata distributed transaction implementation code analysis

Seata is an open source distributed transaction solution , is committed to providing high performance and easy to use distributed transaction services . This article does not involve its principles , only with the code to build a project to try a simple rollback mechanism .

Roughly seata is divided into TC, TM, RM three major construction into a whole. The relationship between them is as follows. That is, one (xid primary key code, record information) with three (TC, TM, RM)

Build the project between the following to test it.

1. Download seata and unzip it, then change the configuration file.

/zh-cn/blog/Official Website Download.

After unzipping, go to conf and modify the file and registry files, always remember to backup before modifying.

Two changes

Define a name for the parameter after the group, at random.

Storage method choose db to put in the database, naturally its configuration information according to their own database to fill in.

Then there is the REGISTER file, fill in the information to register the seata into nacos.

Launching is naturally just a matter of opening the bat file in bin, note that you need to launch Naco first.

2. Build the project (order, storage, account)

Demonstrate the overall service call and also enter rollback when the service reports an error. By creating an order - > checking stock and deducting - > checking account and deducting - > modifying order status

Check out GitHub for the exact code

/MaTsukun/springcloud2020

Key service methods

@Service
@Slf4j
public class OrderServiceImpl implements OrderService{
  @Resource
  private OrderMapper orderMapper;
  @Resource
  private StorageService storageService;
  @Resource
  private AccountService accountService;

  @Override
  @GlobalTransactional(name="abc-create-order",rollbackFor = )
  public void create(Order order){
    //1. Create an order
    ("Start creating orders.");
    (order);
    /2. Reduction of stockpiles
    ("Check inventory and make changes.");
    ((),());
    //3. Deductions
    ("Balance inquiries and deductions.");
    ((),());
    //4. Modification of status
    ("Change Order Status");
    ((),0);
    ("Order closure,O(∩_∩)O(onom.) laughing out loud~");
  }
}

You can see that the methods of both storage and account items are called in the ORDER item, using OPENFEIGN, which overall forms a link to a whole transaction.

The addition of the GlobalTransactional annotation ensures that an error on either side of the transaction will cause the entire project execution to be rolled back, rather than a single-transaction rollback.

Rollback Principle

In each annotated method for the execution of the sql statement will create an id record of the write operation at the same time before and after each write operation will be generated before the record and after the record can be rolled back in the event of an error, through the record for the inverse operation of the rollback to re-write the data back.

You can see the corresponding record id information through the seata library display configured in the database, and pause the service through the debug mode to view the information of the record.

Global xid for global

undo records of the account table

Recorded information in json format

{
  "@class": "", 
  "xid": "192.168.2.141:8091:2060193863", 
  "branchId": 2060193875, 
  "sqlUndoLogs": [
    "", 
    [
      {
        "@class": "", 
        "sqlType": "UPDATE", 
        "tableName": "t_account", 
        "beforeImage": {
          "@class": "", 
          "tableName": "t_account", 
          "rows": [
            "", 
            [
              {
                "@class": "", 
                "fields": [
                  "", 
                  [
                    {
                      "@class": "", 
                      "name": "id", 
                      "keyType": "PrimaryKey", 
                      "type": -5, 
                      "value": [
                        "", 
                        1
                      ]
                    }, 
                    {
                      "@class": "", 
                      "name": "used", 
                      "keyType": "NULL", 
                      "type": 3, 
                      "value": [
                        "", 
                        600
                      ]
                    }, 
                    {
                      "@class": "", 
                      "name": "residue", 
                      "keyType": "NULL", 
                      "type": 3, 
                      "value": [
                        "", 
                        400
                      ]
                    }
                  ]
                ]
              }
            ]
          ]
        }, 
        "afterImage": {
          "@class": "", 
          "tableName": "t_account", 
          "rows": [
            "", 
            [
              {
                "@class": "", 
                "fields": [
                  "", 
                  [
                    {
                      "@class": "", 
                      "name": "id", 
                      "keyType": "PrimaryKey", 
                      "type": -5, 
                      "value": [
                        "", 
                        1
                      ]
                    }, 
                    {
                      "@class": "", 
                      "name": "used", 
                      "keyType": "NULL", 
                      "type": 3, 
                      "value": [
                        "", 
                        700
                      ]
                    }, 
                    {
                      "@class": "", 
                      "name": "residue", 
                      "keyType": "NULL", 
                      "type": 3, 
                      "value": [
                        "", 
                        300
                      ]
                    }
                  ]
                ]
              }
            ]
          ]
        }
      }
    ]
  ]
}

You can see that there are beforeimage and afterimage snapshot records, through which you can realize the reverse operation, rewrite the data to achieve the rollback.

This article is just a simple configuration, and will be added in detail later.

All the code is at GitHub

/MaTsukun/springcloud2020

This is the whole content of this article.