本文共 4754 字,大约阅读时间需要 15 分钟。
本文不介绍LCN理论知识,如不清楚,建议先通过文章进行了解,,该文章中有关于LCN模式的简要说明。
JDK1.8+、Mysql5.6+、Redis3.2+
创建数据库名称为:tx-manager,并在此数据库下新建t_tx_exception表。
DROP TABLE IF EXISTS `t_tx_exception`;CREATE TABLE `t_tx_exception` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `group_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `unit_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `mod_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `transaction_state` tinyint(4) NULL DEFAULT NULL, `registrar` tinyint(4) NULL DEFAULT NULL COMMENT '-1 未知 0 Manager 通知事务失败, 1 client询问事务状态失败2 事务发起方关闭事务组失败', `ex_state` tinyint(4) NULL DEFAULT NULL COMMENT '0 待处理 1已处理', `create_time` datetime(0) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 967 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;
新建一个最基础的SpringBoot工程
#服务名spring.application.name=tx-manager#端口server.port=7970#数据库配置spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://10.0.0.50:3306/tx-manager?characterEncoding=UTF-8&serverTimezone=Asia/Shanghaispring.datasource.username=rootspring.datasource.password=123456#mybatis配置mybatis.configuration.map-underscore-to-camel-case=truemybatis.configuration.use-generated-keys=true#redis配置spring.redis.host=10.0.0.150spring.redis.port=6379#开启日志tx-lcn.logger.enabled=true#TxManager Host IPtx-lcn.manager.host=127.0.0.1#TxClient 连接请求端口tx-lcn.manager.port=8070
com.codingapi.txlcn txlcn-tm 5.0.2.RELEASE com.codingapi.txlcn txlcn-tc 5.0.2.RELEASE com.codingapi.txlcn txlcn-txmsg-netty 5.0.2.RELEASE
SpringApplication,只需要添加一个@EnableTransactionManagerServer即可
import com.codingapi.txlcn.tm.config.EnableTransactionManagerServer;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@EnableTransactionManagerServerpublic class LcnTmApplication { public static void main(String[] args) { SpringApplication.run(LcnTmApplication.class, args); }}
TM最基础的准备就已经完成了,启动服务,访问7970端口,登录TM提供的后台管理,密码默认codingapi。
由于最终需要演示分布式事务,需要TC准备两台SpringCloud服务,服务之间通过Feign进行远程调用。
TC端的配置文件修改很简单,只需要额外添加一个配置项即可
#之间在TM服务里配置的IP、TxClient连接请求端口tx-lcn.client.manager-address=127.0.0.1:8070
com.codingapi.txlcn txlcn-tc 5.0.2.RELEASE com.codingapi.txlcn txlcn-txmsg-netty 5.0.2.RELEASE
SpringApplication,也只需要添加一个@EnableDistributedTransaction即可
import com.codingapi.txlcn.tc.config.EnableDistributedTransaction;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.cloud.openfeign.EnableFeignClients;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@EnableEurekaClient@SpringBootApplication@EnableFeignClients@EnableCircuitBreaker@EnableDistributedTransaction@MapperScan("com.wyl.springcloud.mapper")public class MembershipApplication { public static void main(String[] args) { SpringApplication.run(MembershipApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }}
再搭一个配置一样的服务,最终准备好两台服务,一台order服务,一台member服务。
order服务
/** * 通过添加@LcnTransaction注解,控制分布式事务 */ @LcnTransaction public void update() { ///本地事务 userMapper.update(); }
member服务
/** * 通过添加@LcnTransaction注解,控制分布式事务 */ @LcnTransaction public void update() { //通过feign远程调用order服务 orderFeign.update(); //本地事务 userMapper.update(); //模拟远程调用后,本地执行异常 int i = 1/0; }
启动两台服务后,再看TM系统观后,服务已在线。
演示两台服务之间的调用流程
当前tran_test表数据。
调用服务,异常
两条数据都未被修改,达到分布式事务效果。把member服务的本地异常去掉,再次尝试。
/** * 通过添加@LcnTransaction注解,控制分布式事务 */ @LcnTransaction public void update() { //通过feign远程调用order服务 orderFeign.update(); //本地事务 userMapper.update(); //模拟远程调用后,本地执行异常 //int i = 1/0; }
调用成功
数据修改成功
转载地址:http://hmlrb.baihongyu.com/