Skip to main content

A Guide to Distributed Transaction Patterns

·952 words·5 mins· loading
Table of Contents

Intro
#

2PC (two-phase-commit)
#

Usually, when people hear the word “transaction,” they first think of transactions in an RDB.
It is a core concept of databases that ensures all changes are permanently saved or cleanly rolled back if an error occurs.

However, this is only possible within a single database.

In a distributed architecture, where multiple services have different applications and databases, that is impossible.

To overcome this, distributed transactions emerged to ensure that operations across a distributed environment behave like a single transaction.

In this post, I will summarize the representative distributed transaction patterns : 2PC, TCC, SAGA.


It was the first transaction pattern to emerge. Currently, it is rarely used!!

In 2PC, a central coordinator checks if all participants are ready through the Prepare phase. If everyone says “OK”, it actually reflects the changes in the Commit phase; if there is an error, it rolls back everything.

It is the simplest and most intuitive methods, but it requires the database itself to implement 2PC- such as PostgreSQL’s PREPARE TRANSACTION or MySQL’s XA TRANSACTION . Since it holds database transactions for a long time, it results in low availability, so it is hardly used in practice.

From now on, I will explain using the order, inventory, and point systems as examples. This is a scenario where an order is created while inventory is deducted and points are consumed.

In other words, the order creation, inventory deduction and point usage must all succeed together or fail together.

TCC (Try-Confirm-Cancel)
#

TCC is a method where you first reserve resources (TRY) and then either finalize (Confirm) or roll them back (Cancel).
Here, “Reservation” means holding the resources so that other requests cannot access them, even though they are not actually consumed yet.

The scenario is as follows:

  • Try : Each system temporarily reserves the order, inventory, and points.
  • Confirm: If the try process is successful, a confirmation request is sent to each service => The reserved items are actually applied.
  • Cancel: If an error occurs during the Try process, the previously reserved details are released.

Once the Confirm/Cancel status is finalized, it must be propagated to all services. In other words, even if a network error occurs on the server crashes, consistent state must be guaranteed through retries or manual intervention.

Pros and Cons
#

  • Pros
    • Because resources are first “reserved” and then applied only after confirmation, the propagation of incorrect resource occupation is prevented.
    • In the event of an error, you simply need to release the reservation, so there is a low risk of the compensation (release) process failing.
  • Cons
    • Every service must implement all three stages of TCC, making the design and implementation complex.
    • An additional call is required due to the intermediate Confirm step.

Saga
#

Saga is a method where you first consume resources and then use compensating (rollback) transactions to undo the changes if a failure occurs.

It looks almost identical to TCC, but the difference is that while TCC does not consume actual resources until the Confirm stage, Saga consumes the resources first and then revers them if a problem arises.

The scenario is as follows:

  1. Each System “consumes” all the orders, inventory and points. If everything is successful, it ends there.
  2. If an error occurs, the order is canceled, and the inventory and points are restored by the same amount that was previously consumed.

Pros and Cons
#

  • Pros:
    • Compared to TCC, the API structure is simpler.
    • In a success scenario, it is completed with jus a single call.
  • Cons:
    • Sine resources are actually “consumed”, data inconsistency may occur during the compensation process.
    • If there are external side effects when consuming resources, it can be difficult to achieve a complete restoration during compensation.

TMI
#

Saga can be broadly divided into Orchestration and Choreography methods. Here is a brief overview:

  • Orchestration: A method where a central Orchestrator controls the flow. For example, the Order Service sends requests to the Inventory and Point services respectively and combines the results. It is suitable when results must be returned to the user immediately, but it can lead to excessive coupling between services.

  • Choreography: A method where each service operates independently based on events. For example, the flow moves along an event chain like Order → Inventory → Point → Order. Using a Message Queue (MQ) keeps coupling low, but it makes it difficult to track the entire event flow at a glance.


So, which pattern should you use?
#

  • 2PC is rarely used due to its low availability.
  • TCC is used selectively in cases where data consistency is exceptionally critical.
  • Saga is the most widely used pattern.
    • Choreography Method: Suitable for asynchronous processing and works well when the workflow is simple.
    • Orchestration Method: Primarily used for synchronous processing or when transaction scenarios are complex, allowing for central management of flow and compensation logic.

Final
#

All the patterns described above are bound to encounter errors.

  • 2PC ⇒ What if the commit for DB 1 succeeds, but DB 2 crashes?

  • TCC ⇒ What if all reservations succeed, but the network cuts out during the Point Service’s Confirm stage?

  • Saga ⇒ What if point deduction fails, but the compensation message never reaches the Product Service?

No matter how well you write the code or how perfectly you design the system, you cannot completely avoid errors in distributed transactions.

Therefore, when developing distributed systems, you must design sufficient automatic retries and have a management system ready for manual intervention in the worst-case scenario.

3-Point
#

  1. We explored the distributed transaction patterns: 2PC, TCC, and Saga.

  2. Distributed transactions are bound to encounter errors. The key is how you handle them.

  3. I hope to personally apply these patterns in a real-world project someday.