Implementing TCC Transaction Mode with Seata: Concepts, Types, and Code Example
This article explains the TCC (Try‑Confirm‑Cancel) distributed transaction model, its three phases, three practical variants, and provides a complete Seata‑based Java implementation with code samples, exception handling strategies, and deployment tips for backend services.
This article introduces the TCC (Try‑Confirm‑Cancel) transaction model, a two‑phase commit pattern widely used for flexible distributed transactions, and explains its core idea: each business operation must register a corresponding confirm and cancel (compensate) action.
What is TCC?
TCC consists of two stages. The first stage, Try , performs business checks and reserves resources (e.g., locks). The second stage decides, based on the Try result, whether to execute Confirm (commit) or Cancel (rollback).
TCC Phases
Try : business validation and resource reservation.
Confirm : executes the real business logic and releases locks.
Cancel : releases the reserved resources when the Try fails.
Example: E‑commerce Order
The article uses an order‑placement scenario with two services (inventory and order) to illustrate Try, Confirm, and Cancel steps, showing how inventory is frozen during Try and released or committed in later phases.
Three Practical TCC Variants
1. General‑purpose TCC
All participant services are synchronously invoked; suitable for short‑duration operations such as order, account, and inventory services in an e‑commerce system.
2. Asynchronous‑ensure TCC
Participant services are decoupled via a reliable message service; Confirm and Cancel are executed asynchronously, making it appropriate for low‑sensitivity scenarios like user registration or email sending.
3. Compensation‑type TCC
Participant services provide only Do and Compensate interfaces; the main service still decides the transaction outcome, but rollback is performed via compensation logic.
Seata Integration of TCC
Seata supports multiple transaction modes (AT, TCC, SAGA, XA). The article focuses on TCC implementation.
Demo Scenario
A simplified order service with inventory service is used. The global transaction is started with @GlobalTransactional and the business logic is split into Try, Confirm, and Cancel methods.
@GlobalTransactional
public Result
createOrder(Long productId, Long num, ...) {
// 1. Reduce inventory
reduceStorage();
// 2. Create order
saveOrder();
}Try Method
@Transactional
public boolean try() {
// Freeze inventory
frozenStorage();
// Create order with status 'pending'
saveOrder();
// Add idempotent marker
IdempotentUtil.add(this.getClass().getName() + xid, System.currentTimeMillis());
return true;
}Confirm Method
@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 marker
IdempotentUtil.remove(this.getClass().getName() + xid);
return true;
}Cancel Method
@Transactional
public boolean cancel() {
// Record cancel status in transaction log to avoid hanging
transactionLog.insert(xid, "cancel");
// Idempotency and empty‑rollback protection
if (IdempotentUtil.get(this.getClass().getName() + xid) == null) return true;
// Rollback frozen inventory
rollbackFrozen();
// Delete the pending order
delOrder();
// Remove idempotent marker
IdempotentUtil.remove(this.getClass().getName() + xid);
return true;
}Handling Common TCC Exceptions
The three typical problems are empty rollback, idempotency, and hanging. Solutions include maintaining a transaction‑status table and using an idempotent utility map to record the state of each global transaction.
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;During Cancel, the status is set to "cancel"; before Try executes, the service checks this table to avoid processing a transaction that has already been cancelled, thus preventing hanging.
Other Configuration
The article briefly mentions integrating Nacos, Feign, and ensuring the Seata transaction group (tx‑service‑group) is correctly configured.
Conclusion
TCC provides a relatively simple yet powerful way to achieve distributed consistency; readers are encouraged to download the source code and try the implementation.
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
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.