Implementing TCC Transaction Mode with Seata: Concepts, Types, and Practical Code

This article explains the TCC (Try‑Confirm‑Cancel) transaction model, its three practical variants, common pitfalls such as empty rollbacks, idempotency and hanging, and provides step‑by‑step Java code examples for integrating Seata TCC into a Spring Cloud micro‑service order system.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
Implementing TCC Transaction Mode with Seata: Concepts, Types, and Practical Code

What is TCC?

TCC (Try‑Confirm‑Cancel) is a two‑phase commit pattern where each business operation registers a confirm and a cancel action, enabling flexible distributed transactions.

TCC Phases

Try : resource check and reservation (e.g., lock inventory).

Confirm : execute the real business logic and release locks.

Cancel : roll back reserved resources when the try fails.

Three Practical TCC Types

1. General‑purpose TCC

All participant services are synchronously invoked; suitable for short‑duration operations such as order, account, and inventory services in e‑commerce.

2. Asynchronous‑Assurance TCC

The downstream service is decoupled via a reliable message queue; suitable for low‑time‑sensitivity tasks like email sending.

3. Compensation‑type TCC

Downstream services provide Do and Compensate interfaces; useful when rollback may need manual intervention.

Implementing TCC with Seata

Seata supports AT, TCC, SAGA, and XA modes. The following sections focus on the TCC implementation.

1. Demo Scenario

We use an e‑commerce order flow with only order and inventory services. The order service is the global transaction initiator.

@GlobalTransactional
public Result<Void> createOrder(Long productId, Long num, ...) {
    // 1. Reduce inventory
    reduceStorage();
    // 2. Save order
    saveOrder();
}

The AT mode shown above suffers from long lock times and cannot span multiple applications, so we switch to TCC.

2. TCC Interface Definition

In the order‑boot module, an OrderTccService is created and annotated with @LocalTCC. The @TwoPhaseBusinessAction annotation marks the try method and specifies the confirm and cancel method names.

3. TCC Method Implementations

Try (resource reservation)

@Transactional
public boolean try() {
    // Freeze inventory
    frozenStorage();
    // Create order with status "pending"
    saveOrder();
    // Record idempotent key (class + xid)
    IdempotentUtil.add(this.getClass().getName() + xid, System.currentTimeMillis());
    return true;
}

Confirm (commit)

@Transactional
public boolean confirm() {
    // Idempotency check
    if (IdempotentUtil.get(this.getClass().getName() + xid) == null) return true;
    // Release frozen inventory
    cleanFrozen();
    // Update order status to "completed"
    updateOrder();
    // Remove idempotent record
    IdempotentUtil.remove(this.getClass().getName() + xid);
    return true;
}

Cancel (rollback)

@Transactional
public boolean cancel() {
    // Record cancel status to prevent hanging
    transactionLog.insert(xid, 3);
    // Idempotency & empty‑rollback guard
    if (IdempotentUtil.get(this.getClass().getName() + xid) == null) return true;
    // Restore frozen inventory
    rollbackFrozen();
    // Delete the pending order
    delOrder();
    // Clean idempotent record
    IdempotentUtil.remove(this.getClass().getName() + xid);
    return true;
}

4. Handling the Three TCC Exceptions

Common solutions involve a transaction‑status table ( transactional_record) that records the global XID and its current state (1‑try, 2‑commit, 3‑cancel). This table enables:

Idempotency: check the status before confirm/cancel.

Empty rollback: ensure cancel runs only after a successful try.

Hanging: prevent late‑arriving try after cancel.

CREATE TABLE `transactional_record` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT,
  `xid` varchar(100) NOT NULL,
  `status` int(1) DEFAULT NULL COMMENT '1. try  2 commit 3 cancel',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

5. Order Business Method

@GlobalTransactional
public void placeOrder(Long productId, int quantity) {
    orderTccService.try(); // triggers try, confirm, or cancel automatically
}

6. Additional Configuration

Integrate Seata with Nacos for service discovery, configure Feign clients, and ensure the tx-service-group is set in the Seata configuration.

Conclusion

TCC provides a lightweight, two‑phase transaction alternative to AT, reducing lock time and improving performance for high‑throughput order scenarios. The article supplies the essential code, explains how to avoid empty rollbacks, idempotency issues, and hanging, and points readers to the full source on GitHub.

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.

JavaSpring CloudtccDistributed TransactionsSeata
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.