Integrating Seata‑Golang AT and TCC Modes into Go Microservices

This guide explains how to embed Seata‑Golang’s AT and TCC distributed‑transaction modes into Go microservices, covering global transaction proxy creation, XID propagation via HTTP, Dubbo and gRPC, branch transaction handling, and the required code interfaces and implementations.

Alibaba Cloud Native
Alibaba Cloud Native
Alibaba Cloud Native
Integrating Seata‑Golang AT and TCC Modes into Go Microservices

Seata‑Golang is a distributed‑transaction framework that supports AT (Automatic Transaction) and TCC (Try‑Confirm‑Cancel) modes. AT mode introduces less code intrusion than TCC but holds a global lock on the transaction coordinator, while TCC offers better performance by avoiding the lock.

1. Global Transaction Proxy

In Java, Seata scans methods annotated with @GlobalTransactional to generate AOP proxies. Go, being compiled, uses reflection: objects that need to be proxied must implement the GlobalTransactionProxyService interface.

type GlobalTransactionProxyService interface {
  GetProxyService() interface{}
  GetMethodTransactionInfo(methodName string) *TransactionInfo
}

For the sample aggregation_svc, a proxy struct embeds the original service and declares an empty method CreateSo that Seata‑Golang will fill at runtime.

type ProxyService struct {
  *Svc
  CreateSo func(ctx context.Context, rollback bool) error
}

Developers call tm.Implement(svc.ProxySvc); Seata‑Golang then creates the transaction metadata, executes the original CreateSo logic, and decides to commit or roll back based on the returned error.

2. Propagating the Global Transaction ID (XID)

Three transport mechanisms are demonstrated:

HTTP : The XID is set in the request header ( req.Header.Set("XID", rootContext.GetXID())) and retrieved downstream via c.Request.Header.Get("XID").

Dubbo : When using dubbo‑go, the XID is placed into the attachment map and passed through the RPC context.

context.WithValue(ctx, "attachment", map[string]string{"XID": rootContext.GetXID()})

A custom SeataFilter extracts the XID from the attachment and injects it into the context for the downstream service.

type SeataFilter struct {}
func (sf *SeataFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
  xid := invocation.AttachmentsByKey("XID", "")
  if xid != "" {
    return invoker.Invoke(context.WithValue(ctx, "XID", xid), invocation)
  }
  return invoker.Invoke(ctx, invocation)
}

gRPC : The client adds the XID to outgoing metadata, and the server reads it from incoming metadata.

md := metadata.Pairs("XID", rootContext.GetXID())
ctx = metadata.NewOutgoingContext(context.Background(), md)

Server side:

md, ok := metadata.FromIncomingContext(ctx)
// retrieve XID from md

3. Branch Transaction Handling (AT Mode)

AT mode also requires a proxy for the data source. Seata parses SQL statements to capture before‑and‑after row images for rollback. Developers create a Seata‑compatible DB object by injecting their SQL driver:

db, err := exec.NewDB(config.GetATConfig(), yourSQLDriverInstance)

If using an ORM such as XORM or GORM, extract the underlying driver and wrap it similarly, allowing both the ORM and Seata‑Golang to operate on the same connection.

To start a branch transaction, bind the received XID to a RootContext and call dao.Begin(ctx) to obtain a Tx object.

rootContext := &context.RootContext{Context: ctx}
rootContext.Bind("{XID from upstream}")

tx, err := dao.Begin(ctx)

Execute SQL via tx.Exec(...), then commit or roll back with tx.Commit() or tx.Rollback(). The result is returned to the global transaction manager, which decides the fate of the whole transaction.

4. TCC Mode Integration

TCC requires implementing the TccService interface, whose methods receive a BusinessActionContext. The framework calls Try first; if all branches succeed, it automatically invokes Confirm for commit, otherwise Cancel for rollback.

type TccService interface {
  Try(ctx *context.BusinessActionContext) (bool, error)
  Confirm(ctx *context.BusinessActionContext) bool
  Cancel(ctx *context.BusinessActionContext) bool
}

Developers also create a proxy implementing TccProxyService and register it with tcc.ImplementTCC(proxyInstance). Sample code resides in the samples/tcc directory.

5. References

Seata official site: https://seata.io

Seata Java repository: https://github.com/seata/seata

Seata‑Golang project: https://github.com/opentrx/seata-golang

Dubbo‑go Seata example: https://github.com/dubbo-go-seata (link mentioned in text)

The article concludes that Seata‑Golang is fully compatible with the latest Seata Java 1.4 protocol, making it suitable for mixed Java‑Go stacks that need reliable distributed‑transaction support.

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.

Backend DevelopmentGolangSeataAT ModeTCC Mode
Alibaba Cloud Native
Written by

Alibaba Cloud Native

We publish cloud-native tech news, curate in-depth content, host regular events and live streams, and share Alibaba product and user case studies. Join us to explore and share the cloud-native insights you need.

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.