background

With the rapid development of services and the increasing complexity of services, microservices, as one of the best solutions, decouple services, reduce complexity and increase maintainability, but also bring some new problems.

When we need to ensure data consistency across services, the original database transaction is unable to put multiple operations across libraries and services into one transaction. There are many such application scenarios, and we can list many:

  • In the inter-bank transfer scenario, the data is not in the same database, but it is necessary to ensure that balance deduction and balance increase either succeed or fail at the same time
  • After publishing articles, update statistics such as the total number of articles. Where Posting articles and updating statistics are usually in different microservices
  • Order system after microservitization
  • Travel requires booking several tickets simultaneously on a third-party system

Faced with these scenarios where local transactions cannot be solved, we need a solution of distributed transactions to ensure the consistency of update data across services and databases.

Go-zero has joined forces with DTM to deliver a minimalist solution that seamlessly integrates DTM into Go-Zero, making the use of distributed transactions easier than ever.

Run an example

Let’s look at a working example and then see how we can develop a complete distributed transaction ourselves

Using ETCD as the registration service center, you can run an example of Go-Zero as follows:

  • Configuration DTM
MicroService:
    Driver: 'dtm-driver-gozero' Configure DTM to use go-Zero's microservice protocol
    Target: 'etcd://localhost:2379/dtmservice' Register DTM at this address of etCD
    EndPoint: 'localhost:36790' # DTM local address
Copy the code
  • Start the etcd
# Prerequisite: Etcd etcd is installedCopy the code
  • Start the DTM
Go run app/main.go devCopy the code
  • Run a Go-Zero service
git clone github.com/yedf/dtmdriver-clients && cd dtmdriver-clients
cd gozero/trans && go run trans.go
Copy the code
  • Initiate a DTM transaction with Go-Zero
# CD gozero/app && go run main.go in the dTMdriver-clients directoryCopy the code

When you see it in the trans journal

2021/12/03 15:44:05 transfer out 30 cents from 1
2021/12/03 15:44:05 transfer in 30 cents to 2
2021/12/03 15:44:05 transfer out 30 cents from 1
2021/12/03 15:44:05 transfer out 30 cents from 1
Copy the code

The transaction completes normally

The development of access

Refer to the code for yedf/ dTMdriver-Clients

// The following line imports goZero's DTM driver
import _ "github.com/yedf/dtmdriver-gozero"

// To use DTM's client DTMGRPC, you need to execute the following call, which tells DTMGRPC to use goZero's driver to handle gozero urls
err := dtmdriver.Use("dtm-driver-gozero")
// check err

// DTM is already registered with the following address through the previous configuration, so it is used in DTMGRPC
var dtmServer = "etcd://localhost:2379/dtmservice"

Load is configured from the configuration file, and then get the address of the business service by BuildTarget
var c zrpc.RpcClientConf
conf.MustLoad(*configFile, &c)
busiServer, err := c.BuildTarget()

  // Generate and commit a message-type distributed transaction using DTMGRPC
	gid := dtmgrpc.MustGenGid(dtmServer)
	msg := dtmgrpc.NewMsgGrpc(dtmServer, gid).
    The first step in the / / transaction to invoke trans. TransSvcClient. TransOut
    TransSvc/TransOut/TransSvc/TransOut/TransSvc/ TransSvc/TransOut
    // DTM needs to call this method from the DTM server, so instead of strong type, go dynamic URL: busiServer+"/ trans.transsvc /TransOut"
		Add(busiServer+"/trans.TransSvc/TransOut", &busi.BusiReq{Amount: 30, UserId: 1}).
		Add(busiServer+"/trans.TransSvc/TransIn", &busi.BusiReq{Amount: 30, UserId: 2})
	err := msg.Submit()
Copy the code

The entire development access process is minimal, and the previous comments are clear enough not to go into detail.

Matters needing attention

In the process of developing access, when looking for the GRPC access method path in the *.pb.go file, be sure to look for the invoke path

Understand dynamic invocation in depth

When Go-Zero uses DTM’s distributed transactions, many of the calls are made from the DTM server, such as TCC’s Confirm/Cancel, SAGA/MSG all calls.

DTM does not need to know the strong types of the relevant business apis that make up distributed transactions; it calls these apis dynamically.

The call to GRPC can be analogous to the HTTP POST, where:

  • c.BuildTarget()The resulting target is similar to Host in a URL
  • /trans.TransSvc/TransOutEquivalent to Path in URL
  • &busi.BusiReq{Amount: 30, UserId: 1}Equivalent to Body in Post
  • pb.ResponseEquivalent to a response to an HTTP request

With this part of the code, DTM will have the complete information and be able to make the complete call

Add(busiServer+"/trans.TransSvc/TransOut", &busi.BusiReq{Amount: 30, UserId: 1})

A more complete example

Mikael, a community student, helped to write a more rich example, combining the practical application and sub-transaction barrier, a complete demonstration of a distributed transaction running online, interested students can refer to:

Github.com/Mikaelemmmm…

Other Access Modes

There are other ways to access Go-Zero microservices that are not ETCD, and we’ll explain them in turn

The directly connected

For direct connection, you simply set Target to an empty string based on the ETCD configuration of DTM above.

In the case of direct connection, there is no need to register the DTM with the registry.

K8S

In the case of K8S, you simply set Target to an empty string based on the ETCD configuration of DTM above.

In K8S, the registration of services into K8S is done by deployment.yaml, within the application, and no registration is required.

Live share preview

The Go-Zero author and I (the DTM author) will be doing a live share of the Go-Zero Distributed Transaction Practice on December 22nd at 21pm at GO Night, which will bring more in-depth discussions. You are welcome to join us.

Broadcast address is: live.bilibili.com/11171965

summary

This collaboration between Go-Zero and DTM is significant as it creates the first microservice solution that supports distributed transactions natively in the GO ecosystem.

  • Go-zero project address: github.com/zeromicro/g…
  • DTM project address: github.com/yedf/dtm

Welcome to use Go-Zero and DTM, use our native distributed transaction microservice solution, and star support us!

Wechat communication group

Pay attention to the public account of “micro-service Practice” and click on the exchange group to obtain the QR code of the community group.