Friday, November 4, 2022

Ensuring Data Consistency in Microservice Based Applications

In my previous post I described Oracle’s newly announced product, Oracle Transaction Manager for Microservices (MicroTx). In this post I’ll cover why distributed transactions are needed in a microservice based application and the various distributed transaction protocols supported by MicroTx.

As application architecture moves from monoliths, through SOA, to today’s microservices, issues crop up that monoliths and some SOA based applications don’t need to worry about. One area in particular is around data consistency. In a monolithic application, typically all data is stored in a single database. Consistency across tables is managed by local transactions to ensure the data remains consistent, i.e., an update to two tables either both succeed or neither of them succeed. Moving to microservices where each microservice maintains its own database, local transactions are no longer sufficient to provide consistency.  This is where distributed transactions become a requirement.

Distributed Transactions


To help ensure data consistency across microservices, a distributed transaction is often used. Distributed transactions try to move a system from one consistent state to another consistent state.  hey are often utilized to handle the various failure scenarios that can occur in distributed systems, ideally without burdening the application developer with too much work. One of the earliest distributed transaction protocols is the XA two phase commit protocol defined by The Open Group. Using XA, applications can ensure that the updates to multiple data sources can be done while still adhering to the ACID guarantees of a transaction.

ACID


Transaction protocols typically try to provide ACID guarantees, where ACID is an acronym for:

◉ Atomicity – All changes occur or none of the changes occur – prevents partial updates.
◉ Consistency – The system as a whole move from one consistent state to another consistent state.
◉ Isolation – Changes by one transaction aren’t seen by any other transaction until the transaction is complete - sometimes referred to as serializability meaning the results are the same whether transactions execute in parallel or are serialized.
◉ Durability – Once the outcome of the transaction has been determined, the outcome is durably recorded and will take place even in the presence of temporary failures.

Not all transaction models ensure all these ACID properties. The popular Saga model of eventual consistency for example typically gives up Isolation, which can lead to inconsistent outcomes that are difficult to compensate as a transaction may make a decision based upon potentially dirty or stale data.

XA


The XA standard for Distributed Transaction Processing defines the model and the protocol that occur between the Application Program (microservice), the Transaction Manager, and the Resource Managers (databases). The basic flow is:

1. Application Program asks Transaction Manager to start a transaction
2. Application Program updates one or more Resource Managers
3. Application Program asks Transaction Manager to commit the transaction
4. Transaction Manager asks each Resource Manager to prepare, meaning be ready to commit when asked
5. If all Resource Managers successfully prepare, then the Transaction Manager tells all Resource Managers to commit
6. If a failure occurs before the decision to commit by the Transaction Manager is made, all Resource Managers will be asked to rollback

While the above is greatly simplified, it shows the general flow. From the XA Specification:

Oracle Database, Database Prep, Database Tutorial and Materials, Database Career, Database Skills, Database Jobs, Database

If we replace the monolithic application program with a set of microservices, we will see something like the following picture. A client or other microservice calls A, which starts the XA transaction by calling the Transaction Manager. A’s business logic updates its resource manager and calls B which also calls the transaction manager to enlist in the transaction. B’s business logic does some updates to its resource manager and calls C. Likewise, C calls the transaction manager to enlist in the transaction and its business logic updates its resource manager. Finally, A calls the transaction manager to commit or rollback the transaction. The transaction manager then prepares and commits A, B, and C’s resource mangers or rolls them back.

Oracle Database, Database Prep, Database Tutorial and Materials, Database Career, Database Skills, Database Jobs, Database

Which is a little complicated and we’ll explain how this can be simplified using Oracle Transaction Manager for Microservices (MicroTx) in my next post.

Sagas


Sagas are a distributed transaction model that relies on the idea of eventual consistency. This means that during the execution of the transaction, some microservices are in an inconsistent state with respect to the other microservices involved in the transaction. Sagas provide the advantage that each microservice uses local transactions to maintain consistency within the microservice. This reduces the time locks are held to just the duration of the local transaction instead of for the entire duration of the distributed transaction as is done in XA.

In this picture we can see Sagas look a lot like XA transactions, but with some significant differences. First in Sagas, there isn’t any notion of a resource manager. Another difference is that all the participants use local transactions during the Saga execution instead of a distributed transaction. However, the most significant difference is that the microservice must provide application logic to complete or compensate its part of the Saga. Compensating the microservice’s part of the Saga can become quite complicated as the microservice’s state may have changed due to other Sagas by the time it comes to compensate. How and what completing or compensating means and performed is completely up to the application. This in contrast to XA transactions where the infrastructure takes care of committing or rolling back the state of the involved resource managers.

The basic flow for Saga is:

1. Initiator calls the transaction coordinator to begin a Saga
2. Initiator calls one or more participant microservices
3. The participant microservices enlist in the saga by calling the transaction coordinator to provide their complete and compensate URIs.
4. The initiator then calls the transaction coordinator to complete or compensate the saga
5. The transaction coordinator calls each participant’s complete or compensate URI

Oracle Database, Database Prep, Database Tutorial and Materials, Database Career, Database Skills, Database Jobs, Database

Try-Confirm/Cancel


The Try-Confirm/Cancel transaction model relies on a specific application pattern where microservices provide reservations of resources that will later either be confirmed or canceled. Confirming a reservation means that the resource is now owned by the caller, whereas canceling the reservation means the resource is put back into inventory. It is a two-phase transaction model that doesn’t require locking and the risk of deadlocks or performance issues. However, it is only suitable for application that use a reservation of resources model.

The basic transaction flow for Try-Confirm/Cancel is as follows:

1. Initiator calls the transaction coordinator to begin the Try-Confirm/Cancel transaction
2. Initiator calls one or more participants to make reservations
3. Participants make the reservation and return a URI representing the reservation
4. Initiator calls the transaction coordinator to either confirm or cancel the transaction
5. The transaction coordinator then confirms or cancels all of the reservations using PUT or DELETE

Oracle Database, Database Prep, Database Tutorial and Materials, Database Career, Database Skills, Database Jobs, Database

Later in this series of blog posts, I’ll cover how MicroTx can simplify the use of distributed transactions for each of these models.

Select the Right Protocol for the Required Consistency


By providing multiple distributed transaction protocols, MicroTx allows application developers to choose the level of consistency needed for their microservices. For very strong consistency, developers can choose the XA protocol and get all the ACID properties of a transaction that spans their microservices. One of the benefits of using XA is that it doesn’t require any application logic to ensure consistency. All that’s required is to bracket the beginning and end of a transaction.

Some applications may be better suited for Sagas where the overall transaction time may be quite long, say over the interaction with a user. In these sorts of applications, Sagas in the form of Eclipse MicroProfile Long Running Actions (LRAs) provide a solution. LRAs provide a form of eventual consistency where systems may be inconsistent with one another but will eventually be consistent. One issue with LRAs is that unlike XA, there is no isolation, so other requests may see this temporary inconsistent state across the microservices involved. Also, LRAs require application specific logic to complete as well as compensate a microservice’s involvement in the transaction.

The third supported transaction protocol is the Try-Confirm/Cancel protocol. It relies completely on HTTP verbs to manage a distributed transaction. During the first part of the protocol, the initiator makes POST requests to reserve resources. Once all the resources are reserved, it asks the transaction coordinator to confirm all the reservations. The transaction coordinator then calls PUT on all the resources to confirm the reservation. If all the reservations can’t be made or for some other reason, the initiator can ask the transaction coordinator to cancel all the reservations. The transaction coordinator then calls DELETE on all the reserved resources.

Source: oracle.com

Related Posts

0 comments:

Post a Comment