TxClient配置说明
一、application.properties
# springcloud feign 下开启负载均衡时的配置。开启后同一个事务组下相同的模块会重复调用。
# 对应dubbo框架下需要设置的是 @Reference的loadbalance,有下面四种,作用都是开启后同一个事务组下相同的模块会重复调用。
#txlcn_random=com.codingapi.txlcn.tracing.dubbo.TxlcnRandomLoadBalance
#txlcn_roundrobin=com.codingapi.txlcn.tracing.dubbo.TxlcnRoundRobinLoadBalance
#txlcn_leastactive=com.codingapi.txlcn.tracing.dubbo.TxlcnLeastActiveLoadBalance
#txlcn_consistenthash=com.codingapi.txlcn.tracing.dubbo.TxlcnConsistentHashLoadBalance
tx-lcn.ribbon.loadbalancer.dtx.enabled=true
# tx-manager 的配置地址,多个用,分割。注意设置上的地址在启动的时候会检查并连接,连接不成功会启动失败。
# tx-manager 下集群策略,当增加一个新的tx-manager后,tx-manager也会通知到其他的在线模块,然后tx-client会在连接上后面加入的模块。
tx-lcn.client.manager-address=127.0.0.1:8070,127.0.0.1:8071
# 该参数是分布式事务框架存储的业务切面信息。采用的是h2数据库。绝对路径。该参数默认的值为{user.dir}/.txlcn/{application.name}-{application.port}
tx-lcn.aspect.log.file-path=logs/.txlcn/demo-8080
# 调用链长度等级,默认值为3.标识调用连长度为3,该参数是用于识别分布式事务的最大通讯时间。
tx-lcn.client.chain-level=3
# 该参数为tc与tm通讯时的最大超时时间,单位毫米。该参数不需要配置会在连接初始化时由tm返回。
tx-lcn.client.tm-rpc-timeout=2000
# 该参数为分布式事务的最大时间,单位毫米。该参数不需要配置会在连接初始化时由tm返回。
tx-lcn.client.dtx-time=50000
# 该参数为雪花算法的机器编号。该参数不需要配置会在连接初始化时由tm返回。
tx-lcn.client.machine-id=1
#该参数为事务方法注解切面的orderNumber,默认值为0.
tx-lcn.client.dtx-aspect-order=0
#该参数为事务连接资源方法切面的orderNumber,默认值为0.
tx-lcn.client.resource-order=0
#是否开启日志记录。当开启以后需要配置对应logger的数据库连接配置信息。
tx-lcn.logger.enabled=false
#该参数为tm下的配置,tc下忽略
tx-lcn.client.tx-manager-delay=2000
#该参数为tm下的配置,tc下忽略
tx-lcn.client.tx-manager-heart=2000
二、特别配置
1、微服务集群
且用到 LCN事务模式时,为保证性能请开启TX-LCN重写的负载策略。
- Dubbo 开启
@Reference(version = "${demo.service.version}",
application = "${dubbo.application.e}",
retries = -1,
registry = "${dubbo.registry.address}",
loadbalance = "txlcn_random") // here
private EDemoService eDemoService;
- SpringCloud 开启 (application.properties)
tx-lcn.springcloud.loadbalance.enabled=true
配置详情参见
2、关闭业务RPC重试
- Dubbo 开启
@Reference(version = "${demo.service.version}",
application = "${dubbo.application.e}",
retries = -1,
registry = "${dubbo.registry.address}",
loadbalance = "txlcn_random") // here
private EDemoService eDemoService;
- SpringCloud 开启 (application.properties)
# 关闭Ribbon的重试机制
ribbon.MaxAutoRetriesNextServer=0
NOTE
1、TxClient所有配置均有默认配置,请按需覆盖默认配置。
2、为什么要关闭服务调用的重试。远程业务调用失败有两种可能: (1),远程业务执行失败 (2)、远程业务执行成功,网络失败。对于第2种,事务场景下重试会发生,某个业务执行两次的问题。 如果业务上控制某个事务接口的幂等,则不用关闭重试。
3、通过AOP配置本地事务与分布式事务
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
/**
* 本地事务配置
* @param transactionManager
* @return
*/
@Bean
@ConditionalOnMissingBean
public TransactionInterceptor transactionInterceptor(PlatformTransactionManager transactionManager) {
Properties properties = new Properties();
properties.setProperty("*", "PROPAGATION_REQUIRED,-Throwable");
TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
transactionInterceptor.setTransactionManager(transactionManager);
transactionInterceptor.setTransactionAttributes(properties);
return transactionInterceptor;
}
/**
* 分布式事务配置 设置为LCN模式
* @param dtxLogicWeaver
* @return
*/
@ConditionalOnBean(DTXLogicWeaver.class)
@Bean
public TxLcnInterceptor txLcnInterceptor(DTXLogicWeaver dtxLogicWeaver) {
TxLcnInterceptor txLcnInterceptor = new TxLcnInterceptor(dtxLogicWeaver);
Properties properties = new Properties();
properties.setProperty(Transactions.DTX_TYPE,Transactions.LCN);
properties.setProperty(Transactions.DTX_PROPAGATION, "REQUIRED");
txLcnInterceptor.setTransactionAttributes(properties);
return txLcnInterceptor;
}
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator() {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
//需要调整优先级,分布式事务在前,本地事务在后。
beanNameAutoProxyCreator.setInterceptorNames("txLcnInterceptor","transactionInterceptor");
beanNameAutoProxyCreator.setBeanNames("*Impl");
return beanNameAutoProxyCreator;
}
}
4、TXC模式定义表的实际主键
TXC 是基于逆向sql的方式实现对业务的回滚控制,在逆向sql操作数据是会检索对应记录的主键作为条件处理回滚业务。但是在有些情况下可能表中并没有主键字段(primary key),仅存在业务上的名义主键,此时可通过重写PrimaryKeysProvider
方式定义表对应的主键关系。
如下所示:
@Component
public class MysqlPrimaryKeysProvider implements PrimaryKeysProvider {
@Override
public Map<String, List<String>> provide() {
//t_demo 表的回滚主键为 kid字段
return Maps.newHashMap("t_demo", Collections.singletonList("kid"));
}
}
TxManager配置说明
application.properties
spring.application.name=tx-manager
server.port=7970
#mysql 配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/tx-manager?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.use-generated-keys=true
# TxManager Host Ip 默认为 127.0.0.1
tx-lcn.manager.host=127.0.0.1
# TxClient连接请求端口 默认为 8070
tx-lcn.manager.port=8070
# 心跳检测时间(ms) 默认为 300000
tx-lcn.manager.heart-time=300000
# 分布式事务执行总时间(ms) 默认为36000
tx-lcn.manager.dtx-time=36000
#参数延迟删除时间单位ms 默认为dtx-time值
tx-lcn.message.netty.attr-delay-time=36000
#事务处理并发等级 默认为128
tx-lcn.manager.concurrent-level=128
#后台登陆密码,默认值为codingapi
tx-lcn.manager.admin-key=codingapi
#分布式事务锁超时时间 默认为-1,当-1时会用tx-lcn.manager.dtx-time的时间
tx-lcn.manager.dtx-lock-time=-1
#雪花算法的sequence位长度,默认为12位.
tx-lcn.manager.seq-len=12
#异常回调开关
tx-lcn.manager.ex-url-enabled=false
# 事务异常通知(任何http协议地址。未指定协议时,为TxManager提供的接口)
tx-lcn.manager.ex-url=/provider/email-to/***@**.com
# 开启日志,默认为false
tx-lcn.logger.enabled=true
logging.level.com.codingapi=debug
#redis 的设置信息
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
注意(NOTE)
(1) TxManager所有配置均有默认配置,请按需覆盖默认配置。
(2) 特别注意 TxManager进程会监听两个端口号,一个为TxManager端口
,另一个是事务消息端口
。TxClient默认连接事务消息端口
是8070
, 所以,为保证TX-LCN基于默认配置运行良好,请设置TxManager端口
号为8069
或者指定事务消息端口
为8070
(3) 分布式事务执行总时间 a
与 TxClient通讯最大等待时间 b
、TxManager通讯最大等待时间 c
、微服务间通讯时间 d
、微服务调用链长度 e
几个时间存在着依赖关系。 a >= 2c + (b + c + d) * (e - 1)
, 特别地,b、c、d 一致时,a >= (3e-1)b
。你也可以在此理论上适当在减小a的值,发生异常时能更快得到自动补偿,即 a >= (3e-1)b - Δ
(原因)。 最后,调用链小于等于3时,将基于默认配置运行良好
(4) 若用tx-lcn.manager.ex-url=/provider/email-to/xxx@xx.xxx
这个配置,配置管理员邮箱信息(如QQ邮箱):
spring.mail.host=smtp.qq.com
spring.mail.port=587
spring.mail.username=xxxxx@**.com
spring.mail.password=*********
负载与集群配置
负载集群分为业务模块与TxManager
- 业务模块负载集群说明
模块的集群集群基于springcloud或dubbo机制,集群的方式都是围绕服务发现来完成的,关于模块的负载集群配置这里将不阐述,可参考dubbo与springcloud资料。
- TxManager集群说明
TxManager集群比较简单,只需要控制TxManager下的db资源相同(mysql 、redis)部署多份即可,注意TxManager负载均衡5.0版本与之前版本机制不同。
TX-LCN 负载均衡介绍
使用步骤:
-
首选需要启动多个TxManager服务。
-
在客户端配置TxManager服务地址。
tx-lcn.client.manager-address=127.0.0.1:8070,127.0.0.1:8072
原理介绍:
当有事务请求客户端时事务发起端会随机选择一个可用TxManager作为事务控制方,然后告知其参与模块都与该模块通讯。
目前TX-LCN的负载机制仅提供了随机机制。
- 关于tx-lcn.client.manager-address的注意事项:
-
客户端在配置上tx-lcn.client.manager-address地址后,启动时必须要全部可访问客户端才能正常启动。
-
当tx-lcn.client.manager-address中的服务存在不可用时,客户端会重试链接11次,超过次数以后将不在重试,重试链接的间隔时间为15秒,当所有的TxManager都不可访问则会导致所有的分布式事务请求都失败回滚。
-
当增加一个新的TxManager的集群模块时不需要添加到tx-lcn.client.manager-address下,TxManager也会广播到所有的TxManager端再通知所有链接中的TxClient端新的TxManager加入。
模块端负载集群注意事项
目前TX-LCN支持的事务种类有三种,其中LCN模式是会占用资源,详情见LCN模式原理。
若存在这样的请求链,A模块先调用了B模块的one方法,然后在调用了two方法,如下所示:
A ->B.one();
A ->B.two();
假如one与two方法的业务都是在修改同一条数据,假如两个方法的id相同,伪代码如下:
void one(id){
execute => update demo set state = 1 where id = {id} ;
}
void two(id){
execute => update demo set state = 2 where id = {id} ;
}
若B模块做了集群存在B1、B2两个模块。那么就可能出现A分别调用了B1 B2模块,如下:
A ->B1.one();
A ->B2.two();
在这样的情况下业务方将在LCN下会因为资源占用而导致执行失败而回滚事务。为了支持这样的场景,框架提供了重写了rpc的负载模式。
控制在同一次事务下同一个被负载的模块被重复调用时将只会请求到第一次被选中的模块。
针对dubbo需要指定loadbalance为txlcn的负载方式,框架重写了dubbo的负载方式提供了对应dubbo的四种负载方式 :
txlcn_random=com.codingapi.txlcn.tracing.dubbo.TxlcnRandomLoadBalance
txlcn_roundrobin=com.codingapi.txlcn.tracing.dubbo.TxlcnRoundRobinLoadBalance
txlcn_leastactive=com.codingapi.txlcn.tracing.dubbo.TxlcnLeastActiveLoadBalance
txlcn_consistenthash=com.codingapi.txlcn.tracing.dubbo.TxlcnConsistentHashLoadBalance
使用如下:
@Reference(version = "${demo.service.version}",
application = "${dubbo.application.e}",
retries = -1,
registry = "${dubbo.registry.address}",
loadbalance = "txlcn_random")
private EDemoService eDemoService;
springcloud下需要在application的配置文件下增加:
tx-lcn.springcloud.loadbalance.enabled=true