当前位置:网站首页>Saga architecture pattern: implementation of cross service transactions under microservice architecture
Saga architecture pattern: implementation of cross service transactions under microservice architecture
2022-06-12 15:49:00 【Dotnet cross platform】
In the server application , We tend to go through Transaction processing To ensure data consistency (Data Consistency), for example : When a user takes a certain number of items from inventory , These items will be shown on the user's bill of lading , meanwhile , The number of items in stock should also be reduced . If the consistency of data cannot be guaranteed in this process , Then it is possible that the user fails to take away the item , The number of items in stock has decreased ; Or the user successfully takes away the item , The number of items in stock has not changed . The former causes the total amount of goods to be less than the actual amount , The latter, in turn, leads to a larger total quantity of goods than it actually is , Such a problem is the data consistency problem . To ensure that the application does not have such problems , We usually use them Database transactions . There is a lot of knowledge about database transactions alone , But that's not what we're going to talk about here . We will focus on the implementation of cross service transactions under the microservice architecture and the related Saga Architecture pattern , But before that , It is still necessary to review some of the transaction processing solutions .
Local transactions
Local transactions are usually in the same resource manager (Resource Manager) The complete , The most common example is to operate multiple data tables on the same database , After these operations are completed , Changes to the data table succeed or fail at the same time . for example , Below C# The code will update two data tables simultaneously in a local transaction :
|
In the code SqlTransaction Can guarantee , about Users Table and Inventory The table can be updated successfully at the same time , Or fail at the same time . This local transaction is in the SQL Server On the resource manager of , therefore , The efficiency of local transactions is relatively high .
In the microservices architecture , We tend to choose Database-per-Service The design of the , The advantage of this is that it can obtain better data isolation , And different services can choose different data storage schemes according to their own characteristics . therefore , In terms of individual services , Implementing local transactions is relatively easy , It can well meet the business needs of the service itself , It can also ensure the consistency of data . But obviously , Local transactions cannot guarantee data consistency across Services .
Distributed transactions
Distributed transactions tend to span multiple resource managers (Resource Manager,RM), And distributed transaction coordinator (Distributed Transaction Coordinator,DTC) Be responsible for affairs coordination . Distributed transactions are usually based on a two-stage commit protocol (Two-phase Commit, 2PC) Realization : Transaction commit occurs in two phases , In the first phase ( Preparation stage ) in ,2PC The agreement needs to ensure that DTC Has obtained all information from RM Submit feedback for , For each RM,DTC Both need to know clearly whether it can successfully complete its local transactions , Or it can't be done . Just RM for , At this stage, it attempts to commit its local transaction , If you can successfully submit , to DTC The report “ You can submit ” The state of , Otherwise, the report “ Unable to submit ” The state of .DTC After collecting all participants RM After the state of , If it's all “ You can submit ”, Then start the second stage ( Submission phase ), Inform all RM Complete the formal submission ; But just one RM The report “ Unable to submit ”, be DTC Will inform others RM Cancel commit operation .
A successful 2PC The submission process can be roughly represented by the following sequence diagram :
Besides , Three paragraph submission agreement (Three-phase commit, 3PC) It is also a mode to implement distributed transactions , And 2PC comparison ,3PC Mainly to solve DTC perhaps RM In case of failure , It will 2PC The first stage of ( Preparation stage ) Subdivided , take RM Divided into Awaiting and pre-commit Two kinds of state . in general ,3PC and 2PC The process is roughly the same , You can refer to this article for more information , I won't say much here .
from 2.0 Version start ,.NET Framework Introduced a very convenient class :TransactionScope, This class can assist in distributed transaction processing , such as , The following pseudocode enables cross SQL Server Server transactions :
|
However , It takes a certain cost to obtain such convenience : First , Cross database transaction processing is very inefficient ; secondly , Not all database drivers can support TransactionScope, also , The above code needs to be executed successfully , You need to make sure Windows In the operating system Distributed Transaction Coordinator The service is in the startup state , And the communication between the application and the service cannot be interrupted .
chart :Microsoft Distributed Transaction Coordinator service
However, in the microservice Architecture , Data consistency cannot be guaranteed through distributed transactions , The reasons are as follows :
2PC/3PC The protocol is a blocking protocol , Its own characteristics make the distributed transaction coordinator a single point in the whole system , once DTC An error occurred , Easily lead to RM In a state of waiting for a long time , Resources are not released , This makes the service unavailable . Or further , If in the submission phase , One of the services really failed to submit , And how to maintain the consistency of the state among the services ? It is not impossible to solve such a problem , But the cost will be relatively large , and , This is not implemented under the microservice architecture 2PC/3PC The only drawback of the agreement
be based on 2PC/3PC The distributed transaction processing of the protocol is inefficient , Because it is blocking , So the service itself needs to complete the commit or rollback before continuing to process other transactions , In a microservice environment , One such block may affect many service instances
Not all databases or infrastructure can support 2PC/3PC agreement , It should be said that most of them do not support . The infrastructure I have used to support distributed transactions includes Microsoft SQL Server database 、Oracle Database and Microsoft MSMQ, therefore , There are certain restrictions on technical selection : If your microservice uses data storage / Data transmission technology is not these , Then it is difficult to implement distributed transactions . Besides , The distributed transaction coordinator itself has many limitations , As mentioned above MSDTC Only in Windows Server Up operation
This distributed transaction processing method breaks the design principle of microservice architecture :Database-per-service The design of requires that microservices cannot access each other's databases , and DTC The existence of , The details of database implementation have to be exposed , otherwise DTC Failed to complete cross database transaction coordination
Saga Pattern : Cross service transactions
In the microservices architecture , Transactions tend to span multiple services , This will inevitably depend on the communication mechanism between services . The communication between microservices is divided into synchronous and asynchronous , Asynchronous communication is the more recommended solution : When designing the microservice Architecture , As far as possible, asynchronous mode should be selected to realize the communication between services , In this way, the decoupling between services can be better realized . In terms of transaction processing , Since it is not an instantaneous operation , It's a long-running task (long-running process), Therefore, it is more suitable to use asynchronous method to complete .Saga The problem that the pattern solves is the cross service transaction processing based on asynchronous message mechanism , Its basic process is , Each microservice handles local transactions by itself , Then send messages to the message queue according to the processing results so that the whole transaction can be processed in the next step , meanwhile , Microservices also listen for messages from other microservices , To decide whether you need transaction compensation (Compensation). When one Saga After the transaction is started , It will perform each of these steps step by step (Saga Step). In every step , Participants with only one instance of the microservice are responsible for the execution of their local transactions , When all the steps have been successfully completed ,Saga The transaction is successfully committed . Of course , If one of the steps fails , Then the previously successful local transaction should be rolled back , Otherwise, data consistency cannot be guaranteed . Because the local transaction that has succeeded at the moment cannot be rolled back , therefore , stay Saga In the pattern , Generally, the effect of local transaction rollback is achieved through compensation operation . The whole process can be roughly represented by the following flowchart :
There are generally two ways to achieve Saga Pattern : Choreography and Coordinated .
Choreography (Choreography)
Choreography Saga In the implementation , Each step will be distributed to each microservice , The correlation of event messages is used to link these Saga The steps are connected in series ,“ layout ” a Saga Transaction flow . for example : The shopping cart micro service sends a “ Create a sales order ” The news of , The order microservice listens to this message and creates a sales order , The inventory micro service listens to this message , Check inventory status , If there is not enough stock , Send out a “ Inventory status check failed ” The news of , Then the order micro service gets this message , Execute a compensation transaction , Mark the order status as “ invalid ”, The shopping cart microservice performs its compensation transactions , Restore the information in the current shopping cart to what it was before the order was created . The whole process , Information exchange between microservices , No third-party components are involved in coordinating the collaboration between them , therefore , This implementation is called “ Choreography ”. The following diagram shows this arrangement Saga The implementation of the :
Choreographic implementation has the following advantages :
The implementation is relatively simple , Especially when the number of microservices involved is small , Choreographic implementation is relatively simple and clear
There is no need to rely on third-party components for coordination , So there are no additional deployment and maintenance costs
But there are also some disadvantages :
When the transaction process is complex , Often a Saga Transactions can involve multiple steps , Choreographic implementation will make the whole transaction process complex and difficult to understand and maintain
Because there is no coordination component , The back and forth of news can easily cause confusion , There are even cases where messages affect each other's cyclic processing ( such as A Send a message to B,B After processing the message, send a message to A, So repeatedly )
Testing and debugging become complicated : You need to start all microservices to debug or test a Saga step
Coordinated (Orchestration)
Coordinated Saga In the implementation , There will be a coordinator role to coordinate Saga Every step of , The coordinator communicates with the microservices through message queues , therefore , It is also based on asynchronous message mechanism . The following diagram shows the coordinated Saga The implementation of the :
Coordinated Saga The implementation has the following advantages :
For the complex process Saga Business , The implementation of coordination is clearer than that of choreography , There will be no confusion of information
From the perspective of a single microservice , It doesn't need to care about being involved in itself Saga After the business , How to collaborate so that Saga Things can go on , It only needs to deal with itself Saga event (Saga Events) Complete the response , therefore , Coordinated Saga It can better realize the separation of concerns of microservices (Separation of Concerns)
about Saga The control of transaction flow is simpler , It is also relatively easy to debug the sending, receiving and processing of messages
Of course , There are also shortcomings. :
Due to the need to introduce an additional coordinator , So the structure is more complicated than the arrangement
For the advantages and disadvantages of choreography and coordination , There are also some views that , The coordinator part of the coordination formula has the possibility of single point failure , In fact, in the microservice system , If more consideration is given to this part in the design , This problem can be avoided , for example , You can take advantage of the mechanism of message queuing , Guarantee Saga The reply event is 、 And is processed only once , that , Even if there are multiple coordinator instances running , Can also guarantee Saga Be able to execute , under these circumstances , The failure of a single Coordinator will not affect the whole system Saga Transaction processing .
by comparison , I prefer a coordinated implementation , On the one hand, it can separate concerns , bring Saga The implementation of the pattern becomes more elegant ; On the other hand , It is easier to extract a specific set of frameworks from the implementation , And then re used in different projects .
Next , Let's take a simple case , To understand the whole Saga Design and implementation of the system .
Case study : Order business Saga Simple implementation of
We choose the order placing process of the shopping website to introduce Saga The implementation of the . To simplify the problem , We will simplify the process of placing orders , And it saves a lot of extra business processing ( For example, the available limit of the customer account should belong to the customer member management micro service , In addition, the increase and deduction of the quota have certain business logic , Here we simply classify it as customer information microservice ), therefore , Don't worry too much about whether such a business process is reasonable . There are such business scenarios now and then :
Customers place orders through the shopping cart system of the website (Sales Order)
Shopping cart microservice Start the process of placing orders , In the process :
First , Will inform Order micro service , You need to create an order , At this time, the order status is Created
then , Customer information microservice Verify whether the current customer account is legal
Next , Customer information microservice reserve ( deduction ) Amount of customer account
Last , Inventory microservices reserve ( deduction ) Quantity of goods in the order
Errors occur at any step of the process , Need to notify the steps that have been performed , So that the changed data can be rolled back , Ensure data consistency . such as , If the reservation of customer account quota fails , You need to set the order status to Aborted, It means that the order has to be cancelled for some reason
below , We are based on such business scenarios , Simply do some design and implementation .
overall design
By simple analysis , It can be learned that :
The completion of the whole transaction needs to involve 4 Different microservices : Shopping cart microservice 、 Order micro service 、 Customer information microservice and Inventory microservices
In different Saga In the transaction step , Some microservices have corresponding compensation operations , The purpose is to Saga When transaction execution fails , It can roll back its local data changes to the state before the change ; Some microservices operate without compensation , For example, check whether the customer account is legal
Every Saga All transaction steps have these states : Waiting for execution (Awaiting)、 Being implemented (Started)、 Successful execution (Succeeded)、 Execution failure (Failed)、 Compensating (Compensating)、 Compensation completed (Compensated) And cancel (Cancelled)
According to each Saga Different states of transaction steps ,Saga It is also stateful : Created (Created)、 Being implemented (Started)、 Undoing (Aborting)、 Has been revoked (Aborted) And successfully complete (Completed)
Based on this analysis , You can get the following design guidance :
One Saga Business ( Hereinafter referred to as Saga) By a number of Saga The transaction steps consist of
Saga It's stateful , Its steps are also , therefore ,Saga It needs to be persisted
Saga Management and Saga A manager is responsible for coordinating the handling of events , be called Saga Manager
Saga Asynchronous messages are used to communicate with micro services
therefore , dependent UML The class diagram is roughly as follows :
There are a few points that roughly explain :
IDataAccessObject Is a data access interface , It provides the function of adding, deleting, modifying and querying the data in a database . In our case , use MongoDB The implementation of the
IEventPublisher It is an event dispatch interface , It can send messages to the message queue . In our case , use RabbitMQ The implementation of the
Saga Manager Will use IDataAccessObject Examples to manage Saga Life cycle of , You can also use IEventPublisher Send out examples Saga news
When SagaEventHandler When a response event from each microservice is received , It will pass. Saga Manager Read the corresponding Saga, And then in Saga State transition on , This triggers the next Saga step ( Or the last one Saga Compensation transaction for step ) Implementation
Saga Maintain the status of itself and its steps , Every Saga Step will have two abstract methods to be implemented , The type used to return the transaction message , And the type of compensation transaction message
The following can be used for execution UML Sequence diagram :
The above sequence diagram shows only once that Saga Event triggered state transition process , In the process , The difficulty is Saga Object gets the current Saga When an event is , How to complete state transition , And generate the corresponding Saga The event . Here are some brief introductions .
Detailed design :Saga Event handling and state transition
stay SagaManager Created Saga after , Would call StartAsync Method , The first one. Saga Step Of Saga Events are sent to the message queue , after ,SagaManager It listens to its own message queue to get processing feedback messages from different microservices . In this Saga In the processing logic of the feedback message event , The event handler will respond to the event based on the SagaId, adopt SagaManager Read Saga example , Then perform a state transition . for example , The following code is in Saga Feedback message event processing logic , It's done Saga State transition :
|
stay TransitAsync In the method ,Saga Through the state transition of the received feedback message , And send out the next Saga Step The news of :
|
Saga Of ProcessEvent The process is as follows :
In the flow chart above :
The blue box and the red box indicate on this node , Will get the next Saga Step or previous Saga Generated by step Saga event , This event will be sent to the message queue by the following processing logic
The blue box indicates , At present Step Successfully executed ,Saga The status of will be transferred to the next step for execution , And read the next step Saga event
A red box indicates , At present Step Successfully executed ,Saga The status of will be transferred to the previous step for execution , And read the compensation event of the previous step
The grey dashed box process is not ProcessEvent The main responsibilities of the method , But in order to maintain the integrity of the process , I'll fill this part with a dotted line
Besides , It is worth mentioning that , Not all steps need to be compensated , such as , about “ Customer information microservice Verify whether the current customer account is legal ” This step , If one of its subsequent steps fails , Then this step does not need to be compensated , Because it does not produce any changes in the state of domain objects by itself . In this case , In the red box “ Go back to the last Step” You need to iterate over each previous step in turn , Find the steps that need to be compensated .
In our case , each Saga The steps are defined as follows :
about “ Compensation event type ” This column is not empty Saga step , It requires transaction compensation , therefore , When Saga When execution fails and backtracking occurs , You need to obtain compensation events in these steps and send them to the corresponding microservices , To complete the transaction compensation .
Realization effect
Suppose we only allow customers to reserve at most 1000 RMB account limit , And only reserve no more than in the inventory 5000 A commodity , So if you create an order , The parameter given by the requestor does not exceed this range , Then all microservices should answer “ success ” news , That is, the corresponding event type should also be “ success ”:
Suppose we request an inventory reservation greater than 5000:
You can see : When reserve-inventory The response to the event is false when , There are two compensation events :compensate-reserve-credit and compensate-create-sales-order, And the processing responses of these two compensation events are true:
Query database status , according to SagaStatus and SagaStepStatus The values of the two enumerations ,Saga The status of is Aborted:
of Saga Let's introduce the general design and implementation of , In fact, there are many other contents , You can refer to the case code in this article :
https://github.com/daxnet/byteart-retail-msa
Saga The framework related code is here :
https://github.com/daxnet/byteart-retail-msa/tree/main/src/ByteartRetail.TestClients.Common/Sagas
CQRS Medium Saga
By the way , stay CQRS Architecture pattern ,Saga The implementation of has its own “ duty ”:
Command Receive command , Issue domain events
Saga Receive domain events , Give orders
How to understand ?
Command Part after receiving the command from the client , Can manipulate domain model objects , The result of state changes of domain model objects , Is to send out domain events
Saga After receiving the domain event , Generate their own state transitions , When a state is reached , Give orders again , This affects the domain model
Think more
Realization Saga Things are not that easy , There is still a lot to think about , This article can not cover all , for example :
A more elegant design is to use finite state machines , Use Saga Events as triggers , To complete Saga State transition , for example , Use MassTransit Of Automatonymous frame
how ( Or whether you need ) Ensure the order of message distribution . stay RabbitMQ in , Send to the same Exchange, And by the same RoutingKey Messages on the specified dispatch route , It can ensure its order ; Another example ,Apache Kafka It can guarantee the order of sending and receiving messages . But these frameworks can't guarantee that the application itself processes the messages in the order they are received . therefore , Microservices need to ensure idempotency of message processing
How to ensure that messages are not missed , That is, how to ensure that messages are processed at least once . May adopt Listen To Yourself Pattern ( Refer to my previous article 《ASP.NET Core Web API The implementation of event driven architecture ( 5、 ... and ): The self monitoring mode is used in microservices to ensure the reliability of database update and message distribution 》), You can also use message storage inside microservices , Ensure that undelivered messages are not lost
How to ensure that compensation transactions can really be realized “ compensate ”. If the compensation is not successful , It can also lead to inconsistent data , Final consistency cannot be achieved . It can be used when microservices process compensation transactions , Use similar Retry Or fuse such a mechanism , Try again and again to force compensation to succeed . If you still don't succeed in the end , You need to write it down , Wait for subsequent manual compensation , such as , By email notification , Handled by the administrator
Multiple SagaManager When instances are running at the same time , How to ensure Saga Can be handled correctly . It is usually possible to have multiple running SagaManager The microservice instance of is listening to the same message queue at the same time , So that the feedback message can be processed in the form of polling
I will analyze it slowly when I have a chance .
summary
This article first introduces local transactions and distributed transactions , And introduce... Through the micro service architecture Saga Architecture pattern , To achieve cross service transaction processing . Then through a simple business case , It introduces Saga The overall design and simple implementation of the architecture pattern , Some remaining problems are listed for further consideration and discussion .Saga The implementation of is not the one introduced in this article , But the way introduced in this article is relatively simple and easy to understand . Whole Saga The design system can be abstracted into a development framework , In order to isolate the complexity of state transition and event dispatch , Let developers pay more attention to business implementation .
边栏推荐
- Introduction to microservices
- TS 22.011
- Getting started with JMeter
- Application of postman-rest client plug-in
- Differences between microservice architecture and SOA Architecture
- UE4 常用类型转换
- mysql Blob和Text类型
- Unity get local video / download network video
- Servlet knowledge explanation (2)
- Loadbalancer load balancer
猜你喜欢
Deepin20.6 RTX3080 安装显卡驱动510.60.02、CUDA11.6、PyTorch1.11
Getting started with JMeter
Acwing summer daily question (sexy prime number on June 10)
【光源实用案例】 UV-LED固化创新,让产线变得更丝滑
CUDA out of memory or brokenpipeerror: [errno 32] broken pipe or oserror: [winerror 1455] solution to the problem that the page file is too small
Classic case of solidity - Smart games
鼻孔插灯,智商上升,风靡硅谷,3万就成
ER diagram made by StarUML based on the last student achievement management system
Apache Kylin 历险记
同源?跨域?如何解决跨域?
随机推荐
2021-06-27
[game server design cases] insights
Redis General Command
jupyter notebook新环境快捷方式
Loadbalancer load balancer
Two implementation methods of generic interface
FPGA (III) trigger and latch
[practical case of light source] UV-LED curing innovation makes the production line more smooth
Design concept of ORM framework
Difference between tinyint and int
ER diagram made by StarUML based on the last student achievement management system
Apache Kylin 历险记
From K-means to capsule
How to write year-end summary
sql server 2008 的导入导出步骤
POSTMAN-REST Client插件的应用
Introduction to microservices
一步步创建包含自定义 Screen 的 ABAP 程序的详细步骤
Error 1105: message:\“raft entry is too large
Two ways of array simulating queue