This article focuses on implementing Seata distributed transactions in Spring Cloud. It explains how AT and TCC modes address cross-service data consistency, rollback failures, and high-concurrency lock contention, and provides deployment guidance and code-level practices. Keywords: Seata, distributed transactions, Spring Cloud
Technical Specifications at a Glance
| Parameter | Details |
|---|---|
| Core framework | Seata 2.1.x |
| Microservices stack | Spring Boot 3.2.x, Spring Cloud 2023, Spring Cloud Alibaba 2023 |
| Registry / Configuration Center | Nacos |
| Storage medium | MySQL 8.0 |
| Transaction modes | AT, TCC |
| Communication method | HTTP / OpenFeign / RPC propagation of XID |
| Core dependencies | seata-spring-boot-starter, OpenFeign, MyBatis-Plus |
| Source article characteristics | Original content adapted from a CSDN technical blog; repository Star count not provided |
Distributed transactions are a requirement in microservices, not an option
A monolithic application can rely on local transactions to guarantee ACID. After a system is split into microservices, however, a single order flow often spans multiple services and databases, including order, inventory, and account systems. At that point, @Transactional can only cover a single database and cannot guarantee atomicity across services.
The real challenge is not just failed commits, but partial success: the order is written successfully, inventory is deducted, but account charging fails. Once the system enters an inconsistent state, the cost of compensation is far higher than the cost of addressing the issue during development.
Seata has become a mainstream solution for good reason
Seata splits distributed transactions into three roles: TC, TM, and RM. TC coordinates global transaction state, TM starts and ends global transactions, and RM executes and rolls back local branches.
Its biggest advantage is mode layering: use AT for standard relational database scenarios, and use TCC for hotspot, high-concurrency, or heterogeneous resource scenarios. Development teams do not have to choose between low intrusion and high performance as mutually exclusive options.
AI Visual Insight: This diagram shows Seata’s three-role collaboration flow: TM starts a global transaction in the entry service and requests an XID from TC, the XID is propagated along the call chain to each RM, and each RM executes local business logic while registering branch transactions with TC. TC then makes the unified commit or rollback decision, illustrating the separation between the control plane and the execution plane.
@GlobalTransactional(name = "order-create-tx", rollbackFor = Exception.class)
public String createOrder(...) {
String xid = RootContext.getXID(); // Record the global transaction ID for troubleshooting
log.info("global xid={}", xid);
// Execute business logic and chain remote branch calls
return doCreateOrder();
}
This code declares the boundary of a global transaction and upgrades local business logic into a coordinated distributed transaction.
AT mode fits most relational business scenarios
The core of AT is the data source proxy, undo_log, and the global lock. It intercepts business SQL, records before and after images, and automatically generates reverse SQL for compensation when a branch fails. As a result, business code requires minimal modification.
In phase one, the business SQL and undo_log are committed in the same local transaction, and the local lock is released immediately. In phase two, commit only deletes logs asynchronously, while rollback restores data based on the recorded images. This is the key reason AT is lighter than traditional 2PC.
The guarantees of AT mode depend on undo_log and the global lock
undo_log determines whether automatic rollback is possible, and the global lock determines whether multiple global transactions can be prevented from modifying the same row at the same time. The former governs recovery, and the latter governs isolation. Both are essential.
CREATE TABLE IF NOT EXISTS `undo_log` (
`branch_id` BIGINT NOT NULL,
`xid` VARCHAR(100) NOT NULL,
`context` VARCHAR(128) NOT NULL,
`rollback_info` LONGBLOB NOT NULL, -- Stores before and after images for automatic rollback
`log_status` INT NOT NULL,
`log_created` DATETIME(6) NOT NULL,
`log_modified` DATETIME(6) NOT NULL,
UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
This table is the rollback infrastructure of AT mode. Every business database participating in transactions must create it.
AI Visual Insight: This image presents the two-phase flow of AT mode. In phase one, business SQL is executed, before/after images are captured, undo_log is written, and the branch is registered. In phase two, TC triggers commit or rollback uniformly. The diagram shows that AT exchanges local commit for performance and then uses log-based compensation to achieve eventual consistency.
TCC mode is better suited for high concurrency and heterogeneous resource orchestration
TCC splits a transaction into Try, Confirm, and Cancel. Try performs validation and resource reservation only, Confirm commits the business action, and Cancel releases reserved resources. Because it does not rely on relational database image-based rollback, it works well with Redis, MongoDB, and third-party API calls.
The tradeoff is higher business intrusion. Each branch must implement its own three-phase logic and handle idempotency, empty rollback, and hanging issues. For that reason, TCC should not be the default choice, but it is an excellent fit for critical paths such as flash-sale inventory and payment freezing.
Fence protection should be enabled first when implementing TCC
Seata 1.5.1+ includes built-in TCC Fence, which automatically handles classic issues such as duplicate Confirm/Cancel, Cancel arriving before Try, and delayed Try execution. In production, enabling it should be mandatory.
AI Visual Insight: This diagram illustrates the three-phase resource flow in TCC: Try converts available resources into frozen resources, Confirm transitions frozen resources into consumed resources, and Cancel restores frozen resources back to available resources. It highlights that the essence of TCC is resource reservation rather than direct deduction.
@TwoPhaseBusinessAction(
name = "storageTccService",
commitMethod = "confirm",
rollbackMethod = "cancel",
useTCCFence = true // Enable protection for idempotency, empty rollback, and hanging
)
boolean tryFreezeStorage(BusinessActionContext ctx,
@BusinessActionContextParameter(paramName = "productId") Long productId,
@BusinessActionContextParameter(paramName = "count") Integer count);
This interface definition marks the phase-one entry point of TCC and declares the phase-two commit and rollback methods.
AI Visual Insight: This image summarizes the three major failure semantics in TCC: idempotency issues caused by duplicate calls, empty rollback when Cancel is triggered before Try executes, and hanging when a delayed Try continues reserving resources after Cancel has already completed. It shows that the Fence table is essentially a state-machine-based deduplication layer.
Version and configuration consistency matter most when integrating Seata with Spring Cloud
The recommended combination is Spring Boot 3.2.x, Spring Cloud 2023.x, Spring Cloud Alibaba 2023.x, and Seata 2.1.x. The major versions of the client and server must match. Otherwise, protocol incompatibility, abnormal transaction states, or startup failures can occur easily.
On the server side, Nacos is typically used as the registry and configuration center, and MySQL stores transaction logs. In production, deploy at least three TC nodes that share the same registry and database.
The core Seata Server configuration must align vgroup with the registry
seata:
registry:
type: nacos
config:
type: nacos
store:
mode: db
service:
vgroupMapping:
my_test_tx_group: default # The client tx-service-group must map to this cluster name
This configuration determines whether the client can correctly discover the TC cluster and join the specified transaction group.
A hybrid AT and TCC model is the safer choice for production
Standard CRUD operations such as order creation and status updates are better suited for AT because integration is fast and non-intrusive. High-contention resources such as inventory freezing and quota reservation are better suited for TCC because they avoid global lock contention.
A typical pattern is this: the order service starts a global transaction; the order table and account deduction use AT; inventory freezing uses TCC. This approach preserves development efficiency while moving hotspot paths away from AT lock contention.
// Inventory service degradation must throw an exception and must not return a default value
return (productId, count) -> {
throw new RuntimeException("Inventory service call failed: " + cause.getMessage(), cause);
};
This fallback logic ensures that Seata can detect branch failures. Otherwise, the global rollback may never be triggered.
The most common production issues fall into four categories
First, AT rollback does not occur, usually because the data source is not proxied, undo_log is missing, exceptions are swallowed, or a Feign fallback returns silently. Second, under hotspot data, global lock conflicts become severe and TPS drops quickly.
Third, TCC phase-two method signatures are not implemented correctly, causing Confirm or Cancel to fail. Fourth, a single-point TC deployment or unavailable Nacos can break the entire transaction chain.
A practical checklist for minimizing incidents
- Create the standard
undo_logtable in every business database, and createtcc_fence_logfor TCC scenarios - Always add
rollbackFor = Exception.classto@GlobalTransactional - Feign fallbacks must throw exceptions; never return
falseornull - Print XID in logs to support cross-service tracing
- Migrate hotspot inventory flows to TCC first, while keeping standard CRUD on AT
- Deploy TC, Nacos, and MySQL in clusters
FAQ
FAQ 1: When should you choose AT first, and when is TCC required?
Choose AT first for standard CRUD on relational databases when you want fast integration with minimal code changes. Use TCC first when the flow involves hotspot inventory, balance freezing, Redis, MongoDB, or orchestration of third-party interfaces.
FAQ 2: Why does Seata not roll back even though it has been integrated?
Common causes include an unproxied data source, missing undo_log, catching exceptions without rethrowing them, Feign fallback returning default values, or inconsistency between tx-service-group and the server-side vgroupMapping.
FAQ 3: Can AT and TCC be mixed in the same global transaction?
Yes, and this is a very common production pattern. AT handles standard database updates, TCC handles high-concurrency resource reservation, and both are linked by the same XID under unified coordination by TC.
Key takeaways
This article systematically reconstructs distributed transaction practices with Seata in Spring Cloud microservices, covering the TC/TM/RM architecture, the principles of AT and TCC modes, Nacos plus MySQL cluster deployment, practical order-inventory-account scenarios, hybrid AT+TCC patterns, and production-grade troubleshooting and high-availability recommendations.