2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > TX-LCN(分布式事务框架)

TX-LCN(分布式事务框架)

时间:2019-09-18 13:46:32

相关推荐

TX-LCN(分布式事务框架)

一、环境搭建(搭建TxManager)

(1)导入依赖

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.3.12.RELEASE</version>

</parent>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>Hoxton.SR12</version>

<scope>import</scope>

<type>pom</type>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-tm</artifactId>

<version>5.0.2.RELEASE</version>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-tc</artifactId>

<version>5.0.2.RELEASE</version>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-txmsg-netty</artifactId>

<version>5.0.2.RELEASE</version>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>2.2.0</version>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-tm</artifactId>

</dependency>

</dependencies>

</dependencyManagement>

(2)编写配置文件

spring.application.name=TransactionManager

server.port=7970

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://localhost:3306/tx-manager?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

spring.datasource.username=root

spring.datasource.password=root

# redis配置

spring.redis.host=192.168.8.128

# TM服务器IP修改, TC访问TM时,使用的IP地址。必须精确匹配。默认127.0.0.1。代表TC和TM必须在同一个主机中。

tx-lcn.manager.host=192.168.41.252

# TM服务器日志系统配置,默认关闭日志系统。需要独立配置日志的存储数据库连接

tx-lcn.logger.enabled=false

# 配置TM服务器日志系统数据库连接

tx-lcn.logger.driver-class-name=com.mysql.cj.jdbc.Driver

tx-lcn.logger.jdbc-url=jdbc:mysql://localhost:3306/tx-manager?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai

tx-lcn.logger.username=root

tx-lcn.logger.password=root

# 自动创建表格的配置项。可以自动创建日志表格。

spring.jpa.hibernate.ddl-auto=update

# 修改TM服务器的WEB控制台登录密码, 默认登录密码是 codingapi

tx-lcn.manager.admin-key=bjsxt

# TM事务管理端口。默认 0. 是server.port + 100计算得到。

# tx-lcn.manager.port=7971

(3)编写启动项

/*** EnableTransactionManagerServer - 开启TM服务器功能。** 必须提供配置文件。注意:配置文件只能是properties格式。* 原因:txlcn-tm中包含一个配置文件,命名是application.properties。* 读取优先级高于yml配置文件。所以定义yml配置文件,会被忽略。**/@SpringBootApplication@EnableTransactionManagerServerpublic class MyTMApp {public static void main(String[] args) {SpringApplication.run(MyTMApp.class, args);}}

(4)导入SQL

CREATE DATABASE IF NOT EXISTS `tx-manager` DEFAULT CHARSET utf8 COLLATE utf8_general_ci;

USE `tx-manager`;

SET NAMES utf8mb4;

SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------

-- Table structure for 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(64) 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(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,

`transaction_state` tinyint(4) NULL DEFAULT NULL,

`registrar` tinyint(4) NULL DEFAULT NULL,

`ex_state` tinyint(4) NULL DEFAULT NULL COMMENT '0 待处理 1已处理',

`remark` varchar(10240) NULL DEFAULT NULL COMMENT '备注',

`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;

(5)访问管理平台

通过浏览器访问 http://localhost:7970 。在界面中输入登录密码:bjsxt(默认密码是codingapi)。

二、LCN事务模式

(1)导入依赖

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-tc</artifactId>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-txmsg-netty</artifactId>

</dependency>

</dependencies>

(2)编写配置文件

server:

port: 8001

spring:

application:

name: tx-book-manager

datasource:

driver-class-name: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://localhost:3306/tx-manager?serverTimezone=Asia/Shanghai

username: root

password: root

# 配置TM服务器地址。格式是 ip:port。 ip和端口查看TM WEB控制台中的IP和端口。

tx-lcn:

client:

manager-address: 192.168.41.252:8070

(3)实体类

@Data@NoArgsConstructor@AllArgsConstructorpublic class Book implements Serializable {private Long id;private String name;@DateTimeFormat(pattern = "yyyy-MM-dd")private Date publishTime;private Integer studentId; // 书籍所属学生主键}

(4)数据访问接口

/*** 书籍数据访问对象*/@Mapperpublic interface BookMapper {/*** 新增书籍* @param book* @return*/@Insert("insert into tb_book (id, name, publish_time, student_id) " +"values(#{id}, #{name}, #{publishTime}, #{studentId})")int insert(Book book);/*** 根据学生主键,查询对应的所有书籍* @param studentId* @return*/@Select("select id, name, publish_time as publishTime, student_id as studentId " +"from tb_book where student_id = #{studentId}")List<Book> selectByStudent(Integer studentId);}

(5)编写服务层

@Servicepublic class BookServiceImpl implements BookService {@Autowiredprivate BookMapper bookMapper;/*** 1. 生成主键* 2. 新增数据* @param book* @return*/@Override@LcnTransaction@Transactionalpublic String addBook(Book book) {book.setId(System.currentTimeMillis());int rows = bookMapper.insert(book);if(rows != 1){throw new RuntimeException("新增书籍失败");}return "新增书籍成功";}/*** 根据学生查询书籍* @param studentId* @return*/@Overridepublic List<Book> getBooksByStudent(Integer studentId) {return bookMapper.selectByStudent(studentId);}}

(6)编写控制层

/*** 书籍控制器*/@RestControllerpublic class BookController {@Autowiredprivate BookService bookService;@RequestMapping("/addBook")public String addBook(Book book){return bookService.addBook(book);}@RequestMapping("/getBooksByStudentId")public List<Book> getBooksByStudentId(Integer studentId){return bookService.getBooksByStudent(studentId);}}

(7)编写启动类

/*** EnableDistributedTransaction - 开启分布式事务管理逻辑。* 支持TX-LCN框架的所有分布式事务管理模式。*/@SpringBootApplication@EnableDistributedTransactionpublic class TxBooksManagerApp {public static void main(String[] args) {SpringApplication.run(TxBooksManagerApp.class, args);}}

三、TCC事务模式

(1)导入依赖

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-tc</artifactId>

</dependency>

<dependency>

<groupId>com.codingapi.txlcn</groupId>

<artifactId>txlcn-txmsg-netty</artifactId>

</dependency>

<!-- tc依赖要求,必须连接数据库。

TX-LCN是基于数据库中的表格t_tx_exception,控制事务组

tc依赖,没有数据库连接相关资源。需要独立依赖配置。

-->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

</dependency>

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-redis</artifactId>

</dependency>

</dependencies>

(2)编写配置文件

server:

port: 8002

spring:

application:

name: tx-phone-manager

redis:

host: 192.168.8.128

datasource:

driver-class-name: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://localhost:3306/tx-manager?serverTimezone=Asia/Shanghai

username: root

password: root

tx-lcn:

client:

manager-address: 192.168.41.252:8070

phone:

manager:

keyPref: 'student:phone::'

(3)编辑实体类

/*** 保存在Redis中。* key是 前缀 + 学生主键。*/@Data@NoArgsConstructor@AllArgsConstructorpublic class Phone implements Serializable {private String phoneNo; // 电话号码private Integer studentId; // 电话所属学生主键}

(4)编辑数据访问实体类

@Repositorypublic class RedisDaoImpl implements RedisDao {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Overridepublic void del(String key) {redisTemplate.delete(key);}@Overridepublic void set(String key, Object value) {redisTemplate.opsForValue().set(key, value);}@Overridepublic <T> T get(String key) {T value = (T) redisTemplate.opsForValue().get(key);return value;}}

(5)编写配置类

@Configurationpublic class PhoneManagerConfiguration {/*** redis连接工厂由spring-boot-starter-data-redis自动创建。* 根据配置文件,连接服务器。* @param factory* @return*/protected RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String, Object> redisTemplate =new RedisTemplate<>();// 配置,访问Redis服务器时,如何序列化键值对数据对象。// key使用字符串序列化方式。就是字符串原值。redisTemplate.setKeySerializer(new StringRedisSerializer());// value使用JSON序列化方式。就是把Java对象,转换成JSON字符串并保存。redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());// hash数据的key序列化方案。字符串原值redisTemplate.setHashKeySerializer(new StringRedisSerializer());// hash数据的value序列化方案,JSON格式字符串redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());// 设置Redis连接工厂redisTemplate.setConnectionFactory( factory );return redisTemplate;}}

(6)编写服务层

@Servicepublic class PhoneServiceImpl implements PhoneService {@Autowiredprivate RedisDao redisDao;@Value("${phone.manager.keyPref}")private String keyPrefix;/*** 新增电话* 1. 拼接key* 2. 保存到Redis数据库** 分布式事务参与方法,需要使用注解@TccTransaction注解修饰* 建议:为提示开发者和后期的维护人员,当前方法有事务管理,* 在方法上增加事务管理注解@Transactional。** 使用TCC事务管理模式,做事务控制。* 要求定义confirm和cancel方法。** confirm方法定义要求。实现事务提交逻辑。* 方法名: 是 confirm + try方法名称首字母转大写* 访问修饰符、参数表、返回值、抛出异常,和try方法一致** cancel方法定义要求。实现事务回滚逻辑* 方法名: 是 cancel + try方法名称首字母转大写* 访问修饰符、参数表、返回值、抛出异常,和try方法一致* @param phone* @return*/@Override@TccTransaction@Transactionalpublic String addPhone(Phone phone) {String key = keyPrefix + phone.getStudentId();// 保存到redisredisDao.set(key, phone);return "新增电话成功";}public String confirmAddPhone(Phone phone){System.out.println("事务提交,新增电话结束");return "新增电话成功";}public String cancelAddPhone(Phone phone){// 回滚,就是删除新增的数据String key = keyPrefix + phone.getStudentId();redisDao.del(key);System.out.println("事务回滚,新增的电话已删除");return "新增电话失败";}/*** 根据学生主键,查询电话* 1. 拼接key* 2. 访问redis数据库,查询数据*/@Overridepublic Phone getPhoneByStudent(Integer studentId) {String key = keyPrefix + studentId;Phone phone = redisDao.get(key);return phone;}}

(7)编辑控制层

/*** 电话管理控制器*/@RestControllerpublic class PhoneController {@Autowiredprivate PhoneService phoneService;/*** 新增电话号* @param phone* @return*/@RequestMapping("/addPhone")public String addPhone(Phone phone){return phoneService.addPhone(phone);}/*** 根据学生主键,查询电话* @param studentId* @return*/@RequestMapping("/getPhoneByStudent")public Phone getPhoneByStudent(Integer studentId){return phoneService.getPhoneByStudent(studentId);}}

(8)编辑启动类

@SpringBootApplication@EnableDistributedTransactionpublic class TxPhoneManagerApp {public static void main(String[] args) {SpringApplication.run(TxPhoneManagerApp.class, args);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。