Welcome to follow our wechat official account: Shishan100

My new course ** “C2C e-commerce System Micro-service Architecture 120-day Practical Training Camp” is online in the public account ruxihu Technology Nest **, interested students, you can click the link below for details:

120-Day Training Camp of C2C E-commerce System Micro-Service Architecture

directory

First, write first

2. Introduction to business scenarios

Third, further thinking

Fourth, the implementation of TCC distributed transactions

(1)TCC implementation stage I: Try

(2)TCC implementation stage 2: Confirm

(3)TCC implementation stage three: Cancel

Fifth, summary and thinking

First, write first

See a lot of articles about distributed transaction on the Internet before, but most of them are simply introduced the various technical schemes of distributed transaction. Many friends read a lot of articles, still do not know how to distribute transactions in the end, how to use in the project.

So let’s this article, with plain English + manual drawing, and combined with a case of e-commerce system practice, to tell you clearly what is TCC distributed transaction.

First of all, there may be some principles involved in Spring Cloud. If you are not sure, you can refer to the previous article: “Please, please don’t ask me the underlying principles of Spring Cloud in the interview!” .

2. Introduction to business scenarios

Let’s take a look at the business scenario. Suppose you now have an e-commerce system with a payment order scenario.

After paying for an order, we need to do the following steps:

  • Change the status of the order to paid
  • Deduct goods inventory
  • Add points to members
  • Create sales out order to notify warehouse of shipment

This is a realistic set of steps that should be understood by anyone who has ever worked on an e-commerce system.

Third, further thinking

Ok, now that the business scenario is in place, let’s take it a step further and implement a TCC distributed transaction effect.

What does that mean? That is to say, order service – modify order status, inventory service – deduct inventory, points service – increase points, warehousing service – create sales outbound order.

These steps will either succeed or fail together and must be a holistic transaction.

For example, now that the order status is changed to “paid,” the inventory service fails to deduct the inventory. The stock of that product used to be 100 pieces, but now it has sold 2 pieces, which should have been 98 pieces.

The result? Because the inventory service operation database is abnormal, the inventory quantity is still 100. This is not cheating, of course, can not be allowed to happen!

But if you don’t use TCC distributed transaction solutions and use the Spring Cloud to develop such a microservice system, it’s likely to do the same thing.

Let’s take a look at the diagram below, which visually illustrates the above process.

Therefore, it is necessary to use the TCC distributed transaction mechanism to ensure that each service forms an integrated transaction.

All of the above steps will either succeed, or if any of the service operations fail, they will all be rolled back together to undo the completed operations.

For example, if the inventory service fails to reduce the inventory, the order service must cancel the operation that changed the status of the order, and then stop performing the operations of increasing credits and notifying out of the inventory.

Said so much, the old rules, give you a picture, everybody follow the picture to intuitive experience.

Fourth, the implementation of TCC distributed transactions

So how do you implement a TCC distributed transaction so that the services either succeed together? Or fail together?

Just calm down and let’s go through it step by step. Let’s take a Spring Cloud development system as a backdrop.

1. TCC implementation Stage 1: Try

First, the code for the order service should look something like this:

If you’ve read the Spring Cloud architecture principles article and have some familiarity with the Spring Cloud, you should be able to understand the above code.

After the order service completes the local database operation, the Spring Cloud Feign invokes other services.

But this code alone is not enough to implement TCC distributed transactions. ! Guys, don’t worry, let’s make some code changes to this order service.

First, the above order service changes its status to orderStatus.updating.

What does that mean? In the pay() method, you should not change the order status to paid. You need to change the order state to UPDATING.

This state is a state that doesn’t have any meaning, it means that someone is modifying the state.

Then, in the reduceStock() interface that the inventory service provides directly, don’t directly reduce inventory either, you can freeze inventory instead.

For example, your original inventory quantity is 100, you do not directly 100-2 = 98, deduct this inventory!

You can set the saleable inventory: 100-2 = 98, set it to 98, and then set it to 2 in a separate frozen inventory field. That is to say, two inventories were frozen.

The addCredit() interface for the points service is the same. Don’t add points directly to the user. You can start by adding integrals in a pre-increment integrals field in the integrals table.

For example: user integral originally is 1190, now want to increase 10 integral, do not directly 1190 + 10 = 1200 integral ah!

You can keep the credits at 1190 and set a 10 in a prepare_add_credit field, for example, to say there are 10 credits ready to be added.

The saleDelivery() interface for the warehouse service is the same. You can create a sales order first, but the status of the sales order is “UNKNOWN”.

That is to say, just created this sales order, at this time is not sure what its status is!

This process of interface transformation is actually the so-called TCC distributed transaction in the first T stands for phase, namely the Try phase.

To sum up, if you want to implement a TCC distributed transaction, first of all, the main flow of your business and the business implications provided by the various interfaces are not to do that business operation directly, but to do a Try operation.

This operation usually locks a resource, sets the state of a preparatory class, freezes some data, and so on.

Let’s take a look at the picture below and take a look at the whole process with the words above.

2. TCC implementation Stage 2: Confirm

Then there are two cases. The first case is ideal, that is, each service executes its own Try operation, all execute successfully, and bingo!

At this point, you need to rely on the TCC distributed transaction framework to facilitate subsequent execution.

As a quick note, if you want to play TCC distributed transaction, you must introduce a TCC distributed transaction framework, such as ByteTCC, Himly, tCC-Transaction.

Otherwise, the tasks of perceiving the execution of each phase and advancing the execution of the next phase are unlikely to be done by hand. It’s too complicated.

If you introduce a TCC distributed transaction framework for each service, the TCC distributed transaction framework embedded in the order service can sense that each service’s Try operation succeeded.

At this point, the TCC Distributed transaction framework controls the next phase of TCC, the first C phase, which is the Confirm phase.

To achieve this phase, you need to add some more code to each service.

For example, in the order service, you can add Confirm logic, which formally sets the status of the order to “paid”, something like this:

Similarly for inventory services, you can have a InventoryServiceConfirm class that provides the Confirm logic of a reduceStock() interface, which reduces two inventory deductions from the previously frozen inventory field to zero.

In this case, the sales inventory has been changed to 98 before, and the two frozen inventories are gone, so the inventory deduction is officially completed.

Similarly, you can provide a CreditServiceConfirm class with the Confirm logic of the addCredit() interface, which deducts 10 credits from the pre-added field and adds them to the actual membership points field, from 1190 to 1120.

Warehouse services are similar. You can provide a WmsServiceConfirm class in the warehouse service, which provides the Confirm logic of the saleDelivery() interface to formally change the status of the sales outgoing order to “created”, which can be reviewed and used by the warehouse manager. Instead of staying in the previous intermediate state of “UNKNOWN”.

Once the TCC distributed transaction framework inside the order service senses that the Try phase of each service has succeeded, it will execute the Confirm logic for each service.

The TCC transaction framework within the order service communicates with the TCC transaction framework within the other services, calling the Confirm logic of each service in turn. The execution of all business logic for each service is then formally completed.

Again, I’m going to give you a picture of what’s going on.

3. TCC implementation Stage 3: Cancel

Ok, so this is a fairly normal situation, but what if it’s an abnormal situation?

For example, in the Try phase, for example, the integral service, what happens if he fails?

The TCC transaction framework within the order service is aware of it, and it decides to roll back the entire TCC distributed transaction.

That is, the second PHASE C of each service, the Cancel phase, is performed.

Again, to implement the Cancel phase, each service has to add some code.

First, the order service must provide an OrderServiceCancel class with Cancel logic for the Pay () interface that sets the status of an order to “CANCELED.”

The inventory service is the same, which can provide the Cancel logic of reduceStock(), that is, subtract 2 from frozen inventory and add it back to saleable inventory, 98 + 2 = 100.

The credits service also needs to provide the addCredit() interface’s Cancel logic to deduct 10 credits from the pre-added credits field.

The warehouse service also needs to provide a Cancel logic for the saleDelivery() interface that changes the status of a sales order to CANCELED set to “CANCELED.”

At this point, the TCC distributed transaction framework of the order service will communicate with the TCC distributed transaction framework within each service as long as it senses that the Try logic of any service has failed, and then call the Cancel logic of each service.

Take a look at the picture below and get a feel for it.

Fifth, summary and thinking

Ok, guys, now that we’re talking, you probably know what TCC distributed transactions are all about.

To summarize, if you want to play TCC distributed transactions:

The first step is to select some kind of TCC distributed transaction framework, which will be running in each service.

And then you have one interface, and you have three try-confirm-cancel.

  • First, the service invocation link executes the Try logic in turn
  • If all goes well, the TCC distributed transaction framework advances the Confirm logic to complete the transaction
  • If there is a problem with a service’s Try logic, the TCC distributed transaction framework senses that and pushes forward to execute each service’s Cancel logic, undoing the various operations previously performed

This is known as a TCC distributed transaction.

The core idea of TCC distributed transactions, to put it bluntly, is that when the following situations occur,

  • The database of a service is down
  • A service failed on its own
  • The redis, ElasticSearch, MQ infrastructure for that service is down
  • Some resources are insufficient, such as inventory

Let’s Try it first. Don’t finish the business logic. Let’s Try it first.

If the Try is ok, then the underlying database, Redis, ElasticSearch, MQ are all writable, and you have some resources that need to be used (for example, some inventory is frozen).

Then, execute the Confirm logic of each service, and basically Confirm can guarantee the completion of a distributed transaction with a high probability.

If a service fails in the Try phase, say the underlying database is dead, or Redis is dead, etc.

The Cancel logic for each service is automatically executed, the previous Try logic is rolled back, and all services do not execute any of the designed business logic. Make sure we either succeed together or fail together.

At this point, this article is almost over. Wait a minute. Have you thought of a question?

If something unexpected happens, such as the order service suddenly hangs and then restarts, how does the TCC distributed transaction framework guarantee that the previously unfinished distributed transaction will continue to execute?

Therefore, TCC transaction frameworks are designed to log the activity of distributed transactions, either in a log file on disk or in a database. The phases and states of distributed transaction execution are saved.

That’s not all. What if a service’s Cancel or Confirm logic keeps failing?

That’s easy. The TCC transaction framework logs the status of individual services through activity logging.

For example, if a service fails to Cancel or Confirm, it will try again and again to invoke its Cancel or Confirm logic until it succeeds!

Of course, if you don’t have any bugs in your code, have enough tests, and have basically tried the Try phase, then Confirm and Cancel will usually work!

Finally, here is another diagram to see the entire execution flow of our business with distributed transactions:

Many large companies actually develop TCC distributed transaction frameworks for internal use, such as ours.

However, if your company is not developing a TCC distributed transaction framework, you will generally choose an open source framework.

ByteTCC, TCC-Transaction, himly.

If you are interested, go to their Github address to learn how to use it and how to integrate it with Spring Cloud, Dubbo and other service frameworks.

By integrating those frameworks into your system, you can easily achieve the fantastic TCC distributed transaction effect above.

In the next article, we will look at distributed transactions for the implementation of the Reliable message Final consistency scheme and talk about the high availability assurance architecture that applies this scheme in real production.

See “99.99% High Availability Assurance Production Practices for Final Consistent Distributed Transactions” for details.

If there is any harvest, please help to forward, your encouragement is the biggest power of the author, thank you!

A large wave of micro services, distributed, high concurrency, high availability **** original series

The article is on its way,Please scan the qr code belowContinue to pay attention to:

Architecture Notes for Hugesia (ID: Shishan100)

More than ten years of EXPERIENCE in BAT architecture