Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

The implementation principle of database distributed transaction!

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)06/01 Report--

Transaction is a very interesting and important concept in database system, it is a logical unit in the execution process of database management system, it can guarantee that all operations in a transaction are either executed or not executed; today, with the popularity of SOA and micro-service architecture, ensuring business consistency in distributed multiple services requires us to implement distributed transactions.

In this article, we will introduce the implementation principle of transaction, the theoretical basis and implementation principle of distributed transaction.

Business

At the beginning of the article, we have already said that a transaction is a logical unit in the execution of a database management system, which ensures that a set of database operations are either performed or not executed at all. we can migrate the database from one state to another through transactions, and the data in the database is consistent in each state.

Database transactions have four features, Atomicity, Consistency, Isolation, and Durability:

We often abbreviate these four features as ACID, and the implementation principle of database transaction is actually the principle of realizing these four features.

Realization principle

In the previous article, "shallow in and out", the implementation of transactions in MySQL has actually given a more detailed introduction and analysis on how to achieve the basic attributes of transaction ACID. Here, we briefly introduce several important implementation details. About the content of deployment, you can read the above article.

Transaction log

To ensure that the transaction can be rolled back (atomically) during any execution and that committed transactions are permanently stored in the database, we will use transaction logs to store changes in the database during transaction execution. Each transaction log contains the ID of the transaction, the elements currently modified, and the values before and after the change.

Once we have the above transaction log, it is very easy to roll back the transaction, and the database will generate an opposite operation based on the above log to restore the pre-transaction state. In addition to being able to roll back transactions to ensure atomicity, transaction logs can also achieve persistence. When a transaction routinely modifies the database, it will actually turn into a log and refresh it to disk. The log writing operation is very fast because it is appended, and then the corresponding records will be written or updated to the database.

In InnoDB, the most common storage engine of MySQL, there are actually two kinds of transaction logs, one is rollback log (undo log), and the other is redo log (redo log), in which the former ensures the atomicity of the transaction and the latter ensures the persistence of the transaction, both of which can be called transaction log.

Concurrency control

As the most critical back-end service, it is difficult to imagine the performance impact of only serial execution of each database operation. However, the isolation requirements of the database may not be guaranteed in the process of concurrent execution of SQL. In the final analysis, this is the tradeoff between consistency, isolation and performance.

In order to avoid the consistency problems caused by concurrency and meet the isolation requirements of the database, database systems often use concurrency control mechanisms to make full use of machine efficiency as much as possible. The most common concurrency control mechanisms are locks, timestamps and MVCC:

As a pessimistic concurrency control mechanism, locks use locking resources before updating resources to ensure that sessions of multiple databases do not deviate from expectations when they modify a row of records at the same time. Timestamps check whether the resource has been changed each time it is committed.

In talking about database concurrency control-locking and MVCC, the author introduces the implementation principles of several different concurrency control mechanisms. If you want to know more about it, you can read this article.

Distributed transaction

In a broad sense, distributed transactions are also transactions, but due to the definition of business and the design of micro-service architecture, it is necessary to ensure the transactionality of business among multiple services, that is, the four features of ACID. When changing from a stand-alone database transaction to a distributed transaction, there is no way to use the relatively reliable method invocation and inter-process communication in the original stand-alone, and because the network communication is often unstable, so there will be obstacles to the transmission of information between services.

The change of communication mode between modules (or services) is the main reason for the complexity of distributed transactions. Executing multiple pieces of code between the same transaction will cause all kinds of strange problems because of the instability of the network. When we request the interfaces of other services through the network, we often get three kinds of results: correct, failure and timeout. Whether it is success or failure, we can get the only definite result. The timeout means that the initiator of the request is unable to determine whether the recipient has successfully processed the request, which is also the cause of many problems.

The reliability of communication between systems has changed from the reliability in a single system to the unreliability between micro-service architectures. Distributed transactions actually realize the characteristics of transactions under unreliable communication. Neither transaction nor distributed transaction implementation atomicity can avoid dependence on persistent storage. Transactions use logs on disk to record the process and context of execution, so that whether rollback or compensation is required, they can be traced back through logs, and distributed transactions also rely on services such as database, Zookeeper or ETCD to track the execution of transactions. Various forms of logging is an important means to ensure the characteristics of transactions.

2PC and 3PC

Two-phase commit is a protocol designed to make all nodes consistent when committing transactions in a distributed system. In a distributed system, although all nodes can know their own state after performing operations, they cannot know the state of operations performed by other nodes. When a transaction spans multiple systems, it is necessary to introduce a component as a coordinator to control all nodes and indicate whether these nodes actually commit the results of the operation. Other protocols that want to achieve consistency in distributed systems are improvements based on two-phase commit.

As the name suggests, the execution process of two-phase commit is divided into two stages, the voting phase and the commit phase. During the voting phase, the Coordinator asks the transaction participant (Cohort) whether the operation can be performed and waits for a response from other participants. The participant will perform the corresponding transaction operation and record the redo and rollback logs. All participants who execute successfully send AGREEMENT or ABORT to the coordinator to indicate the result of the operation.

When all participants return a definite result (consent or termination), the two-phase commit enters the submission phase, and the coordinator will send commit or rollback instructions to all participants according to the return of the voting phase.

When all participants in a transaction decide to commit the transaction, the coordinator sends a COMMIT request to the participant. The participant returns a completion message to the coordinator after completing the operation and releasing resources, and the coordinator ends the entire transaction when he receives the completion message from all participants. In contrast, when a participant decides to ABORT the current transaction, the coordinator sends a rollback request to the transaction participant, who rolls back the operation based on the rollback log of the previous operation and sends a completed message to the coordinator. During the commit phase, all resources are released and the transaction is bound to end, regardless of whether the current transaction is committed or rolled back.

The two-phase commit protocol is a blocking protocol, that is to say, during the execution of the two-phase commit, if the coordinator is permanently down during the execution of the transaction, some participants in the transaction will never be able to complete the transaction, they will wait for the coordinator to send COMMIT or ROLLBACK messages, and even multiple participants will have inconsistent states.

3PC

In order to solve some problems of two-phase commit in the protocol, three-phase commit introduces timeout mechanism and preparation phase, if the coordinator or participant does not receive a response from other nodes within the specified period, it will choose to commit or terminate the entire transaction according to the current state, and the introduction of the preparation phase actually gives the transaction participants a choice other than rollback.

When a participant sends an ACK to the coordinator, if the coordinator does not respond for a long time, by default, the participant will automatically commit the timed-out transaction, which will not be blocked as in the two-phase commit. The above picture clearly shows what kind of behavior the coordinator or participant's timeout will cause at different stages.

XA transaction

MySQL's InnoDB engine can actually support distributed transactions, which is often referred to as XA transactions; XA transactions use the two-phase commit protocol we mentioned in the previous section to implement distributed transactions, in which the transaction manager is the coordinator and the resource manager is the participant in the distributed transaction.

At this point, we actually have a clear idea of how XA transactions in MySQL are implemented:

Resource managers provide the ability to access transaction resources. A database is a common resource manager that can commit or roll back transactions it manages.

The transaction manager coordinates all parts of the distributed transaction. It communicates with multiple resource managers and processes the transactions they manage, all of which are a branch of the overall transaction.

As defined in the two-phase commit protocol, the XA interface provided by MySQL can easily implement the voting and submission phases in the protocol. We can briefly understand how the interface of MySQL XA is used through the following flow chart:

XA does guarantee strong consistency, but during the execution of MySQL XA, it will lock the corresponding resources and block the access of other transactions to the resources. if the transaction does not have COMMIT or ROLLBACK for a long time, it will have a serious impact on the database.

Saga

In fact, two-phase commit can ensure the strong consistency of transactions, but in many business scenarios, we only need to ensure the final consistency of the business. It is acceptable to have inconsistent data in multiple systems within a certain time window. After the time window, all systems will return consistent results.

Saga is actually a simplified distributed transaction solution, which converts a series of distributed operations into a series of local transactions. In each local transaction, we update the database and send a new message to other services in the cluster to trigger the next local transaction. Once the local transaction fails because it violates the business logic, a series of rollback operations are immediately triggered to recall the side effects of the previous local transaction.

LLT

Compared with local database transactions, long transactions (Long Lived Transaction) will hold some database resources for a relatively long time, which will seriously affect the execution of other normal database transactions. In order to solve this problem, Hector Garcia-Molina and Kenneth Salem published a paper Sagas in 1987 to solve this problem.

If a LLT can be rewritten into a series of interlaced and overlapping database transactions, then the LLT is a Saga; database system that can ensure that a series of transactions in Saga are either executed successfully or their compensated transactions can roll back all the side effects, ensuring the ultimate consistency of the whole distributed transaction. The concept and implementation of Saga are very simple, but it has great potential to increase the processing power of the whole system.

The longer and more complex the transaction is, the more likely the transaction will be rolled back and deadlocked due to exceptions. Saga will decompose a LLT into multiple short transactions, which can significantly reduce the risk of the transaction being rolled back.

Coordination and arrangement

When we use the Saga pattern to develop distributed transactions, there are two ways to coordinate different services, one is Choreography, the other is Orchestration:

If we develop a distributed transaction in a collaborative manner, each local transaction triggers the execution of a local transaction in another service, that is, the execution of the transaction is in the form of a stream:

When we choose to use a collaborative approach to deal with transactions, the communication between services is actually carried out through events, and each transaction will eventually send a new event to the downstream of the service, which can be either a message in the message queue or a request from RPC, but the interface provided downstream needs to be idempotent and reentrant.

In addition, the distributed transaction created by collaboration actually has no obvious centralized node, and the interaction protocol between multiple service participants should be defined globally. The events and interfaces that each service can handle and send need to be carefully designed to provide events or interfaces with a high degree of abstraction as far as possible, so that each service can achieve autonomy and reuse existing code and logic.

If we do not want to process distributed transactions in a collaborative way, we can also choose the orchestration method to implement distributed transactions. The orchestration method introduces a centralized coordinator node. We use a Saga object to track the invocation of all subtasks, decide whether to call the corresponding compensation scheme according to the task invocation, and retry when the network request times out:

Here we introduce a centralized "coordinator", which will save the state of the current distributed transaction to the end, and roll back or commit the transaction according to the situation, in the process of service orchestration, we trigger and consider the execution process of the whole transaction from the coordinator itself, which is relatively simple compared to the collaborative way.

Collaboration and orchestration are actually two diametrically opposite modes of thinking. The former emphasizes the autonomy and decentralization of each service, while the latter requires a centralized component to uniformly manage the process of transaction execution. The advantages and disadvantages of both are actually the advantages and disadvantages of centralization and decentralization. Centralization schemes often create a "God service", which contains a lot of work of organizing and integrating other nodes. There will also be a single point of failure, and the decentralized solution will bring inconvenience in management and debugging. When we need to track the execution process of a business, it needs to be carried out across multiple services, increasing the cost of maintenance.

Downstream constraint

When we choose to use Saga to develop distributed transactions, there are certain constraints on the participants of distributed transactions, and each transaction participant needs to ensure that:

Provide interfaces and interfaces to compensate for side effects

Interfaces support reentrant and guarantee idempotency through globally unique ID

In this way, we can ensure that a long transaction can retry when the network traffic times out, and call the rollback interface to achieve our purpose when the transaction needs to be rolled back.

Summary

In fact, Saga completely abandoned the idea of satisfying the four basic characteristics of transactions at the same time, but chose to reduce the difficulty of implementing distributed transactions and the problems caused by resource synchronization and locking, and chose to implement BASE (Basic Availability, Soft, Eventual consistency) transactions to achieve basic business availability and ultimate consistency. In the vast majority of business scenarios, achieving final consistency can basically meet all business needs. In extreme scenarios, we should choose the error-prone implementation of two-phase commit or simply abandon the distributed transaction and use the database transaction in the stand-alone machine instead.

Message service

The reason for the complexity of distributed transactions is that the communication between modules is unstable. When we issue a network request, the possible return result is success, failure or timeout.

Whether the network returns success or failure, it is actually a definite result. When a network request times out, it is actually very difficult to handle. At this time, the caller is not sure whether the request is delivered and will not know the result of the request. However, the message service can guarantee that a certain message will be sent to the caller. Most message services provide two different QoS, that is, the level of service.

The two most common service levels are At-Most-Once and At-Least-Once, the former can guarantee that the sender can not guarantee whether the receiver can receive the message, the message will either be delivered once or will not be delivered, which is not much different from an ordinary network request. At-Least-Once can solve the problem of failed message delivery. It requires the sender to check the delivery result and re-deliver the message in case of failure or timeout. The sender will continue to push the message until the recipient confirms that the message has been received, compared with At-Most-Once,At-Least-Once because it can ensure that the delivery of the message will be used by more people.

In addition to these two common service levels, there is another service level, namely Exactly-Once, which requires not only the sender but also the consumer. It requires the receiver to deduplicate all the messages received, the sender and the receiver to retry the message, and the other to deduplicate the message, both of which are deployed on different nodes. In this way, the communication between the services on each node is Exactly-Once, but it is important to note that Exacly-Once must require the participation of the receiver.

We can implement distributed transactions by implementing message queues of AMQP protocol. Three transaction-related interfaces, tx_select, tx_commit and tx_rollback, are defined in the protocol standards, in which tx_select can open transactions, tx_commit and tx_rollback can commit or roll back transactions respectively.

The underlying principle of using message service to realize distributed transaction is not much different from other methods, but message service can help us to achieve the functions of message persistence and retry, and can provide us with a reasonable API interface for developers to use.

Summary

The implementation of distributed transactions is a very important issue in distributed systems. Today, with the popularity of micro-service architecture and SOA, mastering the principle and use of distributed transactions is a skill that should be mastered as a back-end developer, from 2PC and 3PC for implementing ACID transactions to Saga for BASE compensated transactions, and finally asynchronously ensuring that messages will eventually be consumed successfully by means of transaction messages. In order to increase the throughput and availability of the system, we gradually reduce the consistency requirements of the system.

When the business does not have such a strong demand for consistency, the author usually uses the Saga protocol to design and develop distributed transactions, but in practice, there are almost no business scenarios that require strong consistency transactions, and we can achieve the final consistency. When brain cracks or inconsistencies occur, we can solve almost all the problems by means of compensation.

[original link: https://draveness.me/distributed-transaction-principle]

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report