How to Solve Distributed Transactions in Microservices: From 2PC to TCC and Reliable Messaging

This article analyzes the challenges of distributed transactions in microservice architectures, explains ACID, CAP and BASE theories, compares consistency models, and evaluates practical solutions such as two‑phase commit, local message tables, TCC, and reliable messaging with code examples and implementation details.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
How to Solve Distributed Transactions in Microservices: From 2PC to TCC and Reliable Messaging

Microservice Development and Transaction Challenges

Microservice architecture splits a monolithic application into many loosely coupled services, improving scalability and agility but introducing complex inter‑process communication and distributed transaction problems.

ACID Principles

Atomicity : All steps succeed or none do.

Consistency : Database constraints must remain valid after a transaction.

Isolation : Concurrent transactions do not interfere with each other.

Durability : Once committed, a transaction persists permanently.

Consistency Theory: CAP and BASE

The CAP theorem states that a distributed system can simultaneously guarantee at most two of Consistency, Availability, and Partition tolerance. Many systems choose AP (e.g., Cassandra) or CP (e.g., HBase). BASE (Basically Available, Soft state, Eventual consistency) relaxes strict consistency to achieve higher scalability.

Consistency Models

Strong consistency – all replicas see the same data immediately.

Weak consistency – no guarantee of immediate visibility.

Eventual consistency – replicas converge over time.

Local Transaction

A transaction that runs within a single database and a single process, without involving multiple data sources.

Typical Distributed Transaction Solutions

Two‑Phase Commit (2PC)

Local message table (eventual consistency)

TCC (Try‑Confirm‑Cancel) compensation model

Two‑Phase Commit (2PC)

Based on the XA protocol, 2PC consists of a voting phase where participants report readiness, followed by a commit/rollback phase coordinated by a transaction manager. Drawbacks include a single‑point‑of‑failure for the coordinator, synchronous blocking, and possible data inconsistency if some participants fail to receive the final decision.

Local Message Table (Eventual Consistency)

Inspired by eBay’s approach, business operations write a message to a local table within the same database transaction, then asynchronously forward the message to a message queue (e.g., Kafka). The consumer processes the message and performs its own business logic, retrying on failure. This pattern guarantees eventual consistency while avoiding distributed locks.

DROP TABLE IF EXISTS `rp_transaction_message`;
CREATE TABLE `rp_transaction_message` (
  `id` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Primary key',
  `version` INT(11) NOT NULL DEFAULT '0' COMMENT 'Version',
  `editor` VARCHAR(100) DEFAULT NULL COMMENT 'Editor',
  `creater` VARCHAR(100) DEFAULT NULL COMMENT 'Creator',
  `edit_time` datetime DEFAULT NULL COMMENT 'Edit time',
  `create_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Create time',
  `message_id` VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Message ID',
  `message_body` LONGTEXT NOT NULL COMMENT 'Message content',
  `message_data_type` VARCHAR(50) DEFAULT NULL COMMENT 'Data type',
  `consumer_queue` VARCHAR(100) NOT NULL DEFAULT '' COMMENT 'Consumer queue',
  `message_send_times` SMALLINT(6) NOT NULL DEFAULT '0' COMMENT 'Retry count',
  `areadly_dead` VARCHAR(20) NOT NULL DEFAULT '' COMMENT 'Dead flag',
  `status` VARCHAR(20) NOT NULL DEFAULT '' COMMENT 'Status',
  PRIMARY KEY (`id`),
  KEY `AK_Key_2` (`message_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

The accompanying Java service interface defines methods for saving, confirming, sending, retrying, and deleting messages, as well as pagination support.

Message Handling Logic

Classes such as MessageBiz and AccountingMessageListener illustrate how waiting‑confirm and sending‑timeout messages are processed, how retry intervals are configured, and how dead messages are marked.

Comparison with Conventional MQ ACK

Traditional MQ workflows (produce → persist → ACK → consume → ACK) cannot guarantee message‑send consistency because the producer’s business operation and the message dispatch may succeed or fail independently.

Message‑Send Consistency Issues

Three naive patterns are shown with pseudocode: (1) DB operation then send MQ, (2) send MQ then DB operation, (3) wrap both in a Spring @Transactional. All suffer from scenarios where the DB rolls back but the message remains sent, leading to inconsistency.

TCC Compensation Model

TCC splits a business action into Try (resource reservation), Confirm (final commit), and Cancel (rollback). It offers simpler implementation than 2PC but provides weaker consistency guarantees and requires extensive compensation code.

Reliable Message – Final Consistency (Common Practice)

Many Chinese internet companies adopt reliable‑message patterns, often using RocketMQ’s transactional messages or custom implementations. The typical flow is:

A system sends a “prepared” message to MQ.

If the prepared message succeeds, A executes its local transaction.

On local success, A sends a confirm message; on failure, it sends a rollback message.

B receives the confirm and executes its own transaction.

MQ periodically checks prepared messages and triggers callbacks to resolve uncertain states.

If B’s transaction fails, it retries until success or escalates to manual compensation.

Maximum Effort Notification

This pattern sends a message to downstream services, retries a configurable number of times on failure, and finally gives up, suitable for scenarios with low transactional strictness.

CAP diagram
CAP diagram
Local transaction diagram
Local transaction diagram
Local message table flow
Local message table flow
TCC diagram
TCC diagram
Reliable message flow
Reliable message flow
Maximum effort notification
Maximum effort notification
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

MicroservicesBASE theoryCAP theorem2PCtccDistributed Transactionsreliable messaging
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.