如何通过KDTX实现分布式事务(最终一致性)

1 业务背景
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。通俗的说就是某个操作中的事务跨了多个库,或者是跨了多个服务节点而产生了分布式事务,所以一般来讲就是分库分表或者微服务化导致了分布式事务的产生。而本地事务的所有操作都是在某一个库中进行。
苍穹平台提供的分布式事务解决方案,简称KDTX((Kingdee Distributed Transaction)。KDTX目前的方案是两种,自研TCC框架和最终一致。
最终一致模式适用于资源不需要回滚,只需数据最终一致的情景。如,清理数据失败,记录日志表等等,通过重试让最后可以完成,实现弱一致性。
最终一致模式和TCC模式的不同之处在于,它不能回滚,如果某个阶段出现问题,只能通过重试的方式让事务一直往下走,直到成功为止。
本案例主要是介绍下KDTX的最终一致实现方案。
2 案例实现
本次实现的需求是,在二开的单据上点击保存时,同时保存财务库的单据。
因二开的单据是存在二开库中,与财务库的单据分属不同数据库,如采用本地事务保存的话,系统会报错提示:一个事务内不能同时写入多个数据库,所以需要改造成通过分布式事务来实现。
1 构建测试数据
分别在财务云的应付应用和二开云的应用下创建两张测试单据。
2 在二开的单据的保存操作上绑定操作插件:

3 编写操作插件
package bidt.fys.test.plugin.op;
import kd.bos.db.DBRoute;
import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
import kd.bos.entity.plugin.args.BeginOperationTransactionArgs;
import kd.bos.entity.plugin.args.EndOperationTransactionArgs;
import kd.bos.kdtx.sdk.session.ec.ECGlobalSession;
public class TestSaveFiBillOpPlg extends AbstractOperationServicePlugIn {
@Override
public void beginOperationTransaction(BeginOperationTransactionArgs e) {
ECGlobalSession.begin("TestSave", DBRoute.of("secd"));
}
@Override
public void endOperationTransaction(EndOperationTransactionArgs e) {
ecSavebill();
}
public void ecSavebill(){
ECGlobalSession.register( "fi", "apext", "TestSave", null, "ap");
ECGlobalSession.txCommit();
}
}4 编写微服务插件,serviceFactory的路径应该按照上面插件ECGlobalSession.register的注册第一个云参数和第二个应用参数来构建,遵循这个格式(kd.云参数.应用参数.servicehelper.ServiceFactory)。
package kd.fi.apext.servicehelper;
import kd.bos.dataentity.TypesContainer;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.instance.Instance;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import java.util.HashMap;
import java.util.Map;
public class ServiceFactory {
private static Map<String, String> serviceMap = new HashMap();
private static Log log = LogFactory.getLog("ServiceFactory");
public ServiceFactory() {
}
public static void putService(String serviceName, String serviceImpl) {
serviceMap.put(serviceName, serviceImpl);
}
public static Object getService(String serviceName) {
String className = (String)serviceMap.get(serviceName);
if (className == null) {
String appName = Instance.getAppName();
throw new Runt如何通过KDTX实现分布式事务(最终一致性)
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



