preface

Different versions may cause some bugs. In order to run the project quickly, it is recommended to keep the following versions consistent

Configuration nacos

Github.com/alibaba/nac…

CMD in the bin directory to start the startup

Configuration seata

Github.com/seata/seata…

Enter the conf directory and first modify the registry. Conf configuration center, which is currently nacos

Then modify file.conf, which saves the seata data in the MySQL database

Db_store. SQL db_undo_log. SQL db_undo_log. SQL db_undo_log. SQL db_undo_log. SQL

Several working modes of SEATA

The following modes are all compensation modes except XA mode. In THE AT mode, the rollback code is automatically generated for us. When the business is abnormal, the rollback statement is executed to roll back

The following working modes are briefly introduced here, and then the working principle of AT mode will be analyzed in detail

**1. XA mode **

XA is a strong consistency mode, which uses 2PC to ensure that all resources are committed or rolled back at the same time. It locks resources until the whole global transaction issues commit/rollback, which undoubtedly greatly reduces the application throughput. At the same time, if the global transaction is “lost”, each branch transaction in the prepare state will be locked, and eventually deadlock may occur

2. The AT mode

The Seata AT pattern was evolved to address the potential problem of XA pattern locking resources for a long time

  • Phase one: Business data and rollback log records are committed in the same local transaction, freeing local locks and connection resources.

  • Stage 2:

    • Commits are asynchronous and done very quickly.
    • Rollback is compensated in reverse by the rollback log of one phase.

There is no need to write rollback code in AT mode. This is done using the @GlobalTransactional annotation

3. The TCC mode

The main difference between TCC mode and AT mode is that we need to write custom prepare, COMMIT, and ROLLBACK logic

4. Saga mode

Saga mode is a long transaction solution provided by SEATA. In Saga mode, each participant in the business process submits a local transaction, and when a participant fails, the previous successful participant is compensated. One-stage forward service and two-stage compensation service are implemented by business development

AT pattern example

Git clone github.com/seata/seata…

The boot order is as follows, be careful to change their application. Properties dubo.registry. Address =nacos://127.0.0.1:8848

  1. AccountExampleApplication
  2. StorageExampleApplication
  3. OrderExampleApplication
  4. BusinessExampleApplication

In BusinessExampleApplication

As you can see, two remote methods are invoked, and the global transaction is tested by flag by calling /buy

Finally, @GlobalTransactional meets our transaction requirements. The flag is true and the order is successfully generated and the data is successfully rolled back

Principle of Seata AT mode

  1. Tx1 start local transaction, get local lock, set m-100 = 900
  2. You then need to acquire the global lock before committing the local transaction
  3. Global lock successfully obtained, commit local transaction
  4. Tx2 obtains the local lock and sets m-100 = 800
  5. Tx2 needs to obtain the global lock before submitting the local transaction, because the global lock is held by TX1, so here continuously to obtain the global lock repeatedly
  6. Release the global lock after tx1 logic completes
  7. Tx2 successfully obtained the global lock and committed the local transaction

In Seata AT mode, the global transaction isolation level is Read Uncommitted, so tx1’s global transaction is not committed and TX2 may see its changes

There are two possible problems with the above content

  • What if TX1 / TX2 fails to get the global transaction
  • If the subsequent operation of TX1 causes the global transaction to need to be rolled back, then tx2 obtained m = 900 is an error. How to deal with the data
  1. Tx1 to obtain the local lock, execute m-100 = 900
  2. Tx1 gets the global lock
  3. Tx1 commits the local transaction after obtaining the global lock successfully
  4. Tx2 gets the local lock
  5. Tx2 execute m-100 = 800
  6. Tx2 acquires the global lock, which is held by TX1 continuously and repeatedly
  7. Tx1 continues the subsequent branch transaction, where an exception occurs that causes the global transaction to need to be rolled back
  8. Tx1 will retrieve the local lock for data rollback, but the lock is held by TX2. The current local lock holds the primary key id = 1
  9. Tx1 fails to acquire the local lock. Retry until TX2 times out
  10. Tx2 obtains the global lock timeout, rolls back the local transaction m to 900, releases the local lock
  11. Tx1 successfully obtains the local lock. Check the undo log data and find that the m value is 900, which indicates that the lock can be restored. Perform rollback to restore the m value to 1000

Under the protection of this mechanism, there is no dirty write problem, but there is dirty read problem. For example, if someone queries data in the middle time, the wrong data with M equal to 900 will be obtained

A brief analysis of the execution principle of sample code in AT mode

This is done using a @globalTransactional (timeoutMills = 300000, name = “Dubbo-gts-seata-example “) annotation How is it possible to call a remote method without adding an @Transaction annotation to the remote method

  • TM: Transaction Manager, the Transaction Manager is responsible for starting global transactions and committing or rolling back
  • TC: Transaction Coordinator who coordinates and processes branch transactions
  • RM: Resource Manager
  • Undo log: Rollback logs automatically generated by Seata record data status before and after data changes

  1. When we use @GlobalTransactional to start the global transaction, TM makes a BEGIN request to TC to start the global transaction. The global transaction XID is obtained by rootContext.getXID ()
  2. When to launch the remote invocation logic through the agent call storageDubboService. DecreaseStorage
    • RM registers branch transactions with the TC
    • The XID is bound to the branch transaction, and rootContext.getxID () is used to get the XID value of the current branch transaction
  3. The undo log is generated when the UPDATE SQL statement is executed. The undo log stores the data before and after the update
  4. If flag = false, the data in undo log is finally rolled back
  5. After receiving the rollback request from the TC, RM found the corresponding data in the Undo log based on the XID and Branch TRANSACTION ID, compared the current data with the latter data in the Undo log, and executed the former data for restoration if the latter data is the same
  6. If flag = true, RM will finally receive the submission request and put the request into an asynchronous queue. Then, the request will succeed immediately. Finally, tasks in the queue will delete undo logs asynchronously or in batches

Reference:

  • Seata AT mode
  • How are distributed transactions implemented? Read Seata’s XA schema in depth