https://github.com/dtm-labs/dtm 是一款变革性的分布式事务框架,提供了傻瓜式的使用方式,极大的降低了分布式事务的使用门槛,改变了“能不用分布式事务就不用”的行业现状,优雅的解决了服务间的数据一致性问题。

特性

  • 支持多种语言:支持Go、Java、PHP、C#、Python、Nodejs 各种语言的SDK
  • 支持多种事务模式:SAGA、TCC、XA、二阶段消息(本地消息表,事务消息)
  • 支持多种数据库事务:Mysql、Redis、MongoDB、Postgres、TDSQL等
  • 支持多种存储引擎:Mysql(常用)、Redis(高性能)、MongoDB(规划中)
  • 支持多种微服务架构:go-zero、go-kratos/kratos、polarismesh/polaris
  • 支持高可用,易水平扩展

Java SDK 新版的主要改进

  1. 支持spring cloud微服务系列组件
  2. 引入可插拔的微服务注册中心相关依赖,用户可以根据实际情况引入不同的plugin
  3. 优化了整体包结构

感谢 https://github.com/horseLk 的贡献,这次版本更新,主要由他完成

dtmcli-java新版实现

github仓库地址:https://github.com/dtm-labs/d...

项目结构

|--dtmcli-java-parent # parent module
   |--dtmcli-common # dtmcli common module
   |--dtmcli-core # dtmcli core module
   |--dtmcli-java # dtmcli java client
   |--dtmcli-springcloud # dtmcli springcloud client
   |--*-plugin # dtmcli plugin

image.png

dtmcli-java新版快速开始

dtmcli-java新版本提供了多种不同的实现方式,在对原有Java客户端尽可能兼容的基础上进行了改进优化并对微服务进行了支持。新版本的java客户端提供了多种灵活的实现,可以根据业务场景进行选择。

使用范例

使用HTTP接口开启一个自动生成gid的TCC事务

DtmClient dtmClient;

// 根据dtmsvr自动生成gid
dtmClient.tccGlobalTransaction(new DtmConsumer<Tcc>() {
    @Override
    public void accept(Tcc tcc) throws Exception {
        String svc = "http://127.0.0.1:8888";
        Response outResponse = tcc.callBranch( "", svc + "/TransOutTry", svc + "/TransOutConfirm",
                                              svc + "/TransOutCancel");
      
        Response inResponse = tcc.callBranch("", svc + "/TransInTry", svc + "/TransInConfirm",
                                             svc + "/TransInCancel");
    }
});

// 使用自定义的gid
dtmClient.tccGlobalTransaction("custom_gid_123456", new DtmConsumer<Tcc>() {
    @Override
    public void accept(Tcc tcc) throws Exception {
        String svc = "http://127.0.0.1:8888";
        Response outResponse = tcc.callBranch( "", svc + "/TransOutTry", svc + "/TransOutConfirm",
                                              svc + "/TransOutCancel");
      
        Response inResponse = tcc.callBranch("", svc + "/TransInTry", svc + "/TransInConfirm",
                                             svc + "/TransInCancel");
    }
});

使用微服务接口开启一个TCC事务

DtmClient dtmClient;

// 根据dtmsvr自动生成gid
dtmClient.tccGlobalTransaction(new DtmConsumer<Tcc>() {
    @Override
    public void accept(Tcc tcc) throws Exception {
        String appName = "serviceName";
        tcc.callBranch(new HashMap<>(), new ServiceMessage(appName, "/TransOutTry"),
                new ServiceMessage(appName, "/TransOutConfirm"), new ServiceMessage(appName, "/TransOutCancel"));

        tcc.callBranch(new HashMap<>(), new ServiceMessage(appName, "/TransInTry"),
                new ServiceMessage(appName, "/TransInConfirm"), new ServiceMessage(appName, "/TransInCancel"));

    }
});

// 使用自定义的gid
dtmClient.tccGlobalTransaction("custom_gid_123456", new DtmConsumer<Tcc>() {
    @Override
    public void accept(Tcc tcc) throws Exception {
        String appName = "serviceName";
        tcc.callBranch(new HashMap<>(), new ServiceMessage(appName, "/TransOutTry"),
                new ServiceMessage(appName, "/TransOutConfirm"), new ServiceMessage(appName, "/TransOutCancel"));

        tcc.callBranch(new HashMap<>(), new ServiceMessage(appName, "/TransInTry"),
                new ServiceMessage(appName, "/TransInConfirm"), new ServiceMessage(appName, "/TransInCancel"));

    }
});

使用HTTP接口开启一个SAGA事务

DtmClient dtmClient;
String svc = "127.0.0.1:8888";

// 从dtmsvr获取gid
Saga saga = dtmClient
    .newSaga()
    .add(svc + "/TransOut", svc + "/TransOutCompensate", "")
    .add(svc + "/TransIn", svc + "/TransInCompensate", "")
    .enableWaitResult()
    .submit();

// 自定义gid
Saga saga = dtmClient
    .newSaga("custom_gid_123456")
    .add(svc + "/TransOut", svc + "/TransOutCompensate", "")
    .add(svc + "/TransIn", svc + "/TransInCompensate", "")
    .enableWaitResult()
    .submit();

使用微服务接口开启一个SAGA事务

DtmClient dtmClient;
String serviceName = "serviceName";

// 从dtmsvr获取gid
Saga saga = dtmClient
    .newSaga()
    .add(new ServiceMessage(serviceName, "/TransOut"), new ServiceMessage(serviceName, "/TransOutCompensate"), "")
    .add(new ServiceMessage(serviceName, "/TransIn"), new ServiceMessage(serviceName, "/TransInCompensate"), "")
    .enableWaitResult()
    .submit();

// 自定义gid
Saga saga = dtmClient
    .newSaga("custom_gid_123456")
    .add(new ServiceMessage(serviceName, "/TransOut"), new ServiceMessage(serviceName, "/TransOutCompensate"), "")
    .add(new ServiceMessage(serviceName, "/TransIn"), new ServiceMessage(serviceName, "/TransInCompensate"), "")
    .enableWaitResult()
    .submit();

如何获取DtmClient对象

spring-cloud客户端

DtmClient对象已经注入到容器中,只需要在你需要使用的类中通过@Autowired注解引入即可.

@Autowired
private DtmClient dtmClient;

dtmcli-java客户端

直连dtmsvr

只需要将dtmsvr的服务地址传给构造函数即可。

DtmClient dtmClient = new DtmClient("127.0.0.1:36789");

当然如你想讲直连的地址设置到配置文件中,只需要添加一个命名为dtm-conf.properties的配置文件,配置文件格式如下:

# dtmsvr地址
dtm.ipport=121.4.131.37:36789
使用服务发现

如果您使用了服务发现并且现有支持的springcloud版本不兼容您项目的版本您可以使用dtmcli-java版本,只需要添加一个命名为dtm-conf.properties的配置文件,配置文件格式如下:

# 服务中心地址
serverAddr=127.0.0.1:8848
# 服务中心登录username
username=nacos
# 服务中心登录密码
password=nacos
# namespace
namespace=c3dc917d-906a-429d-90a9-85012b41014e
# dtmsvr注册到服务中心的服务名
dtm.service.name=dtmService
# 服务中心类型
dtm.service.registryType=nacos

注意:我们对一个配置文件有两种不同的配置方式,如果同时使用了两种,会优先选择直连方式。

pom引入dtmcli java客户端

springboot version >= 2.6.0

# dtmcli依赖
<dependency>
  <groupId>io.github.dtm-labs</groupId>
  <artifactId>dtmcli-springcloud</artifactId>
  <version>2.1.4.2</version>
</dependency>
# 使用的服务中心插件,如果您的项目中已经引入了相关依赖,则可以忽略
<dependency>
  <groupId>io.github.dtm-labs</groupId>
  <artifactId>nacos-plugin</artifactId>
  <version>2.1.4.2</version>
</dependency>

2.4.0 <= springboot version < 2.6.0

# dtmcli依赖
<dependency>
  <groupId>io.github.dtm-labs</groupId>
  <artifactId>dtmcli-springcloud</artifactId>
  <version>2.1.4.1</version>
</dependency>
# 使用的服务中心插件,如果您的项目中已经引入了相关依赖,则可以忽略
<dependency>
  <groupId>io.github.dtm-labs</groupId>
  <artifactId>nacos-plugin</artifactId>
  <version>2.1.4.1</version>
</dependency>

其他情况

# dtmcli依赖
<dependency>
  <groupId>io.github.dtm-labs</groupId>
  <artifactId>dtmcli-java</artifactId>
  <version>2.1.4</version>
</dependency>

# 如果有需要也可以引入相应的服务中心插件

dtmcli-java新版快速拓展

目前,dtmcli-java已经支持了部分开源通信服务框架和服务中心框架,后续会针对大家的诉求尽可能支持更多的通信服务框架和服务中心框架。但是如果你的项目使用的公司内部的通信服务框并且想接入dtmsvr您需要完成简单的操作就可以适配您的框架了。

新版客户端提供了IDtmServerStub接口用于拓展不同的通信框架,只需要使用你们项目中使用的通信服务框架实现IDtmServerStub接口,并使用其构造一个DtmClient客户端即可使用。考虑到需要使用自研框架的项目一般不使用开源的springcloud,并且为了防止您的框架和springcloud不兼容引起问题,此构造函数仅在dtmcli-java版本中可以使用。

public DtmClient(IDtmServerStub dtmServerStub) {
    this.dtmServerStub = dtmServerStub;
}

示例代码

dtm-springcloud示例代码

https://github.com/dtm-labs/dtmcli-java-spring-sample

dtm-java使用到spring项目中

https://github.com/dtm-labs/dtmcli-java-sample

基于配置的dtmcli-java使用

https://github.com/horseLk/dtmcli-java-sample-with-conf


叶东富
1.1k 声望6.1k 粉丝