If someone asks you about distributed transactions again, throw this to him

foreword

I don’t know if you have ever encountered such a situation. You went to a small shop to buy something and paid for it, but the shop owner forgot that you paid for it because of some other things, and asked you to pay again. Or I have been charged for online shopping, but told me that no transaction occurred. This series of situations is caused by no transaction. This illustrates some of the importance of affairs in life. With affairs, you go to a small shop to buy things, that is, you pay first and deliver. With a transaction, you go shopping online, and the deduction generates an order transaction.

The specific definition of a transaction

Transactions provide a mechanism to incorporate all operations involved in an activity into an indivisible execution unit. All operations that make up a transaction can only be committed if all operations can be executed normally. Causes a rollback of the entire transaction. Simply put, transactions provide an "all or nothing" mechanism.

database local transaction

ACID

When it comes to database transactions, it has to be said that the four major characteristics of database transactions, ACID:

  • A: Atomicity

All operations in a transaction are either completed or not completed, and will not end at a certain link in the middle. If an error occurs during the execution of the transaction, it will be rolled back (Rollback) to the state before the transaction started, as if the transaction was never executed.

Just like when you buy something, you have to pay and receive the goods, or if you don't ship it, you will get your money back.

  • C: Consistency

Transactional consistency means that the database must be in a consistent state before and after a transaction is executed. If the transaction completes successfully, all changes in the system will be applied correctly and the system will be in a valid state. If an error occurs in the transaction, all changes in the system are automatically rolled back and the system returns to its original state.

  • I: Isolation

Refers to in a concurrent environment, when different transactions manipulate the same data at the same time, each transaction has its own complete data space. Modifications made by concurrent transactions must be isolated from modifications made by any other concurrent transactions. When a transaction views data updates, the state of the data is either the state before another transaction modifies it, or the state after another transaction modifies it, and the transaction does not view the data in the intermediate state.

For example, when you buy something, it doesn't affect other people.

  • D: Durability

This means that as long as the transaction ends successfully, the updates it makes to the database must persist forever. Even in the event of a system crash, restarting the database system restores the database to the state it was in when the transaction ended successfully.

For example, when you buy something, it needs to be recorded on the ledger, even if the boss forgets it, it is well documented.

InnoDB implementation principle

InnoDB is a storage engine of mysql. Most people are familiar with mysql. Here is a brief introduction to some basic principles of database transaction implementation. In local transactions, services and resources can be regarded as one under the package of transactions:

Our local transactions are managed by the resource manager: the ACID of the transaction is guaranteed by the InnoDB log and locks. The isolation of transactions is achieved through the mechanism of database locks, the persistence is achieved through the redo log (redo log), and the atomicity and consistency are achieved through the Undo log. The principle of UndoLog is very simple. In order to satisfy the atomicity of transactions, before operating any data, first back up the data to a place (the place where the data backup is stored is called UndoLog). Then modify the data. If there is an error or the user executes the ROLLBACK statement, the system can use the backup in the Undo Log to restore the data to the state before the transaction started. In contrast to Undo Log, RedoLog records a backup of new data. Before the transaction is committed, as long as the RedoLog is persisted, the data does not need to be persisted. When the system crashes, although the data is not persisted, the RedoLog has been persisted. The system can restore all data to the latest state according to the content of RedoLog. Students who are interested in the specific implementation process can search and expand by themselves.

Distributed transaction

What is Distributed Transaction

Distributed transaction means that transaction participants, transaction-supporting servers, resource servers, and transaction managers are located on different nodes of different distributed systems. Simply put, a large operation consists of different small operations. These small operations are distributed on different servers and belong to different applications. Distributed transactions need to ensure that these small operations either all succeed or all fail. Essentially, distributed transactions are to ensure data consistency across different databases.

Reasons for Distributed Transactions

From the above local transaction point of view, we can see it as two pieces, one is the service that generates multiple nodes, and the other is the resource that generates multiple nodes.

service multiple nodes

With the rapid development of the Internet, microservices, SOA and other service architecture models are being used on a large scale. For example, within a company, the user's assets may be divided into multiple parts, such as balance, points, coupons, etc. Wait. In the company, it is possible that the points function is maintained by a microservice team, and the coupons are maintained by another team. In this case, there is no guarantee that the coupons can be successfully deducted after the points are deducted.

resource multiple nodes

Similarly, the Internet is developing too fast. Generally speaking, our Mysql needs to be sub-database and sub-table to install tens of millions of data. For an Alipay transfer business, if you transfer money to a friend, it is possible that your The database is in Beijing, and your friend's money is in Shanghai, so we still can't guarantee that they will be successful at the same time.

Fundamentals of Distributed Transactions

From the above point of view, distributed transactions came into being with the rapid development of the Internet. This is inevitable. We have said that the ACID four characteristics of the database can no longer satisfy our distributed transactions. At this time, there are some new big Guy proposes some new theories:

CAP

CAP theorem, also known as Brewer's theorem. For architects designing distributed systems (not just distributed transactions), CAP is your starting point.

  • C (Consistency): For a given client, a read operation can return the latest write operation. For data distributed on different nodes, if the data is updated on a certain node, if the latest data can be read by other nodes, it is called strong consistency. If a node does not read the data If you get it, it is distributed inconsistency.
  • A (availability): A non-faulty node returns a reasonable response (not an error and timeout response) in a reasonable amount of time. The two keys to availability are reasonable time and reasonable response. Reasonable time means that the request cannot be blocked indefinitely and should be returned in a reasonable time. A reasonable response means that the system should explicitly return the result and the result is correct, where correct means that it should return 50, not 40, for example.
  • P (Partition Tolerance): The system can continue to work when a network partition occurs. For example, there are multiple machines in a cluster, and there is a problem with the network of one machine, but the cluster can still work normally.

Anyone who is familiar with CAP knows that the three cannot be shared. If you are interested, you can search for the proof of CAP. In a distributed system, the network cannot be 100% reliable, and partitioning is actually an inevitable phenomenon. If we choose CA and give up P, Then when a partition occurs, in order to ensure consistency, the request must be rejected at this time, but A does not allow it, so it is theoretically impossible for a distributed system to choose the CA architecture, only the CP or AP architecture.

For CP, to give up availability and pursue consistency and partition fault tolerance, our zookeeper is actually the pursuit of strong consistency.

For AP, giving up consistency (the consistency mentioned here is strong consistency) and pursuing partition fault tolerance and availability is the choice of many distributed systems when designing, and the latter BASE is also extended according to AP.

By the way, CAP theory ignores network latency, that is, when a transaction is committed, it is copied from node A to node B, but in reality this is obviously impossible, so there will always be some time inconsistency. At the same time, choosing two of the CAP, for example, you choose CP, does not tell you to give up A. Because the probability of P appearing is so small, you still need to guarantee CA most of the time. Even if the partition appears, you have to prepare for the later A, for example, by means of some logs, other machines will be restored to usable.

BASE

BASE is an abbreviation for the three phrases Basicly Available, Soft state and Eventually consistent. It is an extension to AP in CAP

  1. Basic availability: When a distributed system fails, part of the available functions are allowed to be lost, and the core functions are guaranteed to be available.
  2. Soft state: Allows the existence of intermediate states in the system that do not affect system availability, which refers to inconsistencies in CAP.
  3. Eventual consistency: Eventual consistency means that after a period of time, all node data will be consistent.

BASE solves the theory that there is no network delay in CAP, and uses soft state and eventual consistency in BASE to ensure consistency after delay. BASE and ACID are opposites, it is completely different from ACID's strong consistency model, but gains availability by sacrificing strong consistency, and allows data to be inconsistent for a period of time, but eventually reach a consistent state.

Distributed Transaction Solutions

With the above theoretical basis, here are some common solutions for distributed transactions.

Do you really want distributed transactions?

Before talking about the solution, first of all you must clarify whether you really need distributed transactions?

The two reasons for distributed transactions have been mentioned above, one of which is because there are too many microservices. I've seen too many teams maintain several microservices by themselves, too many teams over-engineer, making everyone exhausted, and too many microservices will lead to distributed transactions. At this time, I would not recommend you to use any of the following One solution, but please aggregate the microservices that require transactions into a single-machine service, using the local transaction of the database. Because any solution will increase the complexity of your system, the cost is too high, do not introduce unnecessary cost and complexity because of the pursuit of certain designs.

If you are sure that you need to introduce distributed transactions, you can look at the following common solutions.

2PC

When it comes to 2PC, we have to talk about XA Transactions in database distributed transactions. There are two phases in the XA protocol:

Phase 1: The transaction manager asks each database involved in the transaction to precommit this operation and reflects whether it can be committed.

Stage 2: The transaction coordinator asks each database to commit data, or roll back data.

Advantages: As far as possible to ensure the strong consistency of data, the implementation cost is low, all major mainstream databases have their own implementations, and MySQL is supported from 5.5.

shortcoming:

  • Single point of problem: The role of the transaction manager in the entire process is critical, if it goes down, for example, when the first phase has completed, and the transaction manager is down while the second phase is preparing to commit, the resource manager will Blocked all the time, making the database unusable.
  • Synchronous blocking: After the resource is ready, the resource in the resource manager is blocked until the commit is completed and the resource is released.
  • Data inconsistency: Although the two-phase commit protocol is designed for strong consistency of distributed data, there is still the possibility of data inconsistency. For example, in the second phase, it is assumed that the coordinator sends a transaction commit notification, but the notification is due to network problems. Only some participants have received and performed the commit operation, and the rest of the participants have been in a blocking state because they have not received the notification, which results in data inconsistency.

In general, the XA protocol is relatively simple and low-cost, but its single-point problem and its inability to support high concurrency (due to synchronous blocking) are still its biggest weaknesses.

TCC

The concept of TCC (Try-Confirm-Cancel) was first proposed by Pat Helland in a paper titled "Life beyond Distributed Transactions: an Apostate's Opinion" published in 2007. Compared with the XA introduced above, the TCC transaction mechanism solves several shortcomings: 1. It solves the single point of the coordinator, and the main business party initiates and completes this business activity. The business activity manager has also become multi-point, introducing clusters. 2. Synchronous blocking: Introduce a timeout, compensate after the timeout, and will not lock the entire resource, convert the resource into a business logic form, and reduce the granularity. 3. Data consistency, after the compensation mechanism is in place, the consistency is controlled by the business activity manager. Explanation of TCC:

  • Try phase: try to execute, complete all business checks (consistency), reserve necessary business resources (quasi-isolation)

  • Confirm phase: Confirm that the actual execution of the business is performed, without any business inspection, only use the business resources reserved in the Try phase, and the Confirm operation satisfies idempotency. An idempotent design is required, and a retry is required after a Confirm failure.

  • Cancel phase: Cancel the execution and release the business resources reserved in the Try phase. The Cancel operation satisfies idempotency. The exceptions in the Cancel phase are basically the same as those in the Confirm phase.

As a simple example, if you buy a bottle of water with 100 yuan, try stage: you need to check with your wallet if you have enough 100 yuan and lock the 100 yuan, the same is true for water.

If there is a failure, cancel (release the 100 yuan and this bottle of water), and if the cancel fails, retry the cancel regardless of the failure, so it needs to be kept idempotent.

If it is successful, then confirm, confirm that the 100 yuan deduction, and this bottle of water are sold, if the confirm fails, no matter what fails, retry (will rely on the activity log to retry)

Some suitable for TCC:

  • Active business with strong isolation and strict consistency requirements.
  • Business with shorter execution time

Implementation reference: ByteTCC: https://github.com/liuyangming/ByteTCC/

local message table

The scheme of local message table is originally the complete scheme of eBay proposed by eBay https://queue.acm.org/detail.cfm?id=1394128.

The core of this solution is to execute tasks that require distributed processing asynchronously by means of message logs. Message logs can be stored in local text, databases or message queues, and retry can be initiated automatically or manually through business rules. Manual retry is more used in payment scenarios, and the reconciliation system is used to deal with post-event problems.

The core of the local message queue is to convert large transactions into small transactions. Let's take the example of buying a bottle of water with 100 yuan above.

1. When you deduct money, you need to add a new local message table on the server where you deduct money. You need to put your deduction and write the inventory minus water into the local message table into the same transaction (depending on Database local transactions guarantee consistency.

2. At this time, there is a scheduled task to poll the local transaction table, throw the unsent messages to the commodity inventory server, and ask him to subtract the water inventory. After reaching the commodity server, the transaction of this server must be written at this time. table, and then deduction, after the deduction is successful, update the status in the transaction table.

3. The commodity server scans the message table through a timed task or directly informs the money deduction server, and the money deduction server's local message table updates the status.

4. For some abnormal situations, regularly scan the unsuccessfully processed messages and resend them. After the commodity server receives the message, it first determines whether it is a duplicate. If it has been received, it is determined whether to execute it. If it is executed, it will be notified immediately. If the transaction is not executed, it needs to be re-executed and needs to be guaranteed by the business to be idempotent, that is, it will not deduct an extra bottle of water.

The local message queue is based on the BASE theory and is an eventually consistent model, which is suitable for those who do not require high consistency. Implementing this model requires attention to the idempotency of retries.

MQ transaction

The distributed transaction is implemented in RocketMQ, which is actually an encapsulation of the local message table, which moves the local message table to the inside of MQ. The following briefly introduces the MQ transaction. If you want to know more about it, you can refer to: https:// www.jianshu.com/p/453c6e7ff81c. The basic process is as follows: In the first stage of Prepared message, the address of the message will be obtained.

The second phase performs local transactions.

The third stage accesses the message through the address obtained in the first stage and modifies the state. The message recipient can use the message.

If the confirmation message fails, the RocketMq Broker provides a regular scan for messages that have not been updated. If a message is not confirmed, it will send a message to the sender to determine whether to submit it. In Rocketmq, it is sent to the sender in the form of a listener. , for processing. If the consumption times out, you need to retry all the time, and the message receiver needs to ensure idempotency. If the message consumption fails, this needs to be processed manually, because the probability is low, if you design this complex process for this small probability time, it will outweigh the gains.

Saga affairs

Saga is a concept mentioned in a database ethics article 30 years ago. The core idea is to split a long transaction into multiple local short transactions, which are coordinated by the Saga transaction coordinator. If it ends normally, it will be completed normally. If a step fails, the compensation operation will be called once in reverse order. Composition of Saga:

Each Saga consists of a series of sub-transactions Ti. Each Ti has a corresponding compensation action Ci, which is used to undo the results caused by Ti. Each T here is a local transaction. It can be seen that compared with TCC, Saga does not have a "reserved try" action, and its Ti is directly submitted to the library.

There are two execution orders for Saga:

T1, T2, T3, ..., Tn

T1, T2, ..., Tj, Cj,..., C2, C1, where 0 < j < n Saga defines two recovery strategies:

Backward recovery, that is, the second execution order mentioned above, where j is the sub-transaction with an error, the effect of this approach is to undo all previous successful sub-transations, so that the execution result of the entire Saga is undone. Forward recovery, suitable for scenarios that must succeed, the execution order is similar to this: T1, T2, ..., Tj (failure), Tj (retry), ..., Tn, where j is the error occurred sub-transaction. Ci is not required in this case.

It should be noted here that isolation is not guaranteed in saga mode, because other transactions can still overwrite or affect the current transaction without locking resources.

Or take the example of buying a bottle of water for 100 yuan, here is the definition

T1 = deduct 100 yuan T2 = add a bottle of water to the user T3 = reduce the inventory of a bottle of water

C1=Add 100 yuan C2=Reduce a bottle of water to the user C3=Add a bottle of water to the inventory

We do T1, T2, T3 at a time. If a problem occurs, perform the reverse of the C operation in which the problem occurred. The problem of isolation mentioned above will occur. If the execution reaches T3, a rollback needs to be performed, but the user has already drank the water (another transaction). When rolling back, it will be found that the user cannot be reduced by one. Bottled water. This is the problem with no isolation between transactions

It can be seen that the impact of the saga mode without isolation is still relatively large. You can refer to Huawei's solution: starting from the business level, adding a Session and a lock mechanism to ensure that resources can be serialized. It is also possible to isolate this part of resources by freezing funds in advance at the business level, and finally obtain the latest updates by reading the current status in time during the business operation.

Specific example: You can refer to Huawei's servicecomb

finally

In the same sentence, you don't need to use distributed transactions. If you have to use it, you can use your own business analysis to see which business is more suitable for you. Whether you care about strong consistency or final consistency. The above solutions are just some brief introductions. If you really want to implement them, in fact, each solution has a lot of places to think about, and the complexity is relatively large, so I remind you again that you must judge whether to use distributed transactions. Finally, I summarize some questions, you can come down to find the answers from the article yourself:

  1. Are ACID and CAP's CA the same?
  2. What are the pros and cons of commonly used solutions for distributed transactions? What scenario does it apply to?
  3. The reason for the emergence of distributed transactions? What pain point is it used to solve?

Finally, this article was included in JGrowing, a comprehensive and excellent Java learning route jointly built by the community. If you want to participate in the maintenance of open source projects, you can build it together. The github address is: https://github.com /javagrowing/JGrowing Please give a little star.

If you think this article is helpful to you, you can follow my official account. Your attention and forwarding are the greatest support for me, O(∩_∩)O:

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324106087&siteId=291194637