likes
comments
collection
share

分布式事务【搭建事务管理器】

作者站长头像
站长
· 阅读数 19

1. CAP 定理和 BASE 理论

1.1. CAP(Consistency, Availability, Partition tolerance)

CAP原则又称CAP定理,它描述了分布式系统中的三个基本属性:

  1. 一致性(Consistency) :数据在多个副本之间能够保持一致的特性。即,无论数据被读取或写入哪个副本,所有副本上的数据都应该是相同的。
  2. 可用性(Availability) :系统提供的服务一直处于可用的状态,每次请求都能获得正确的响应。即,系统应该保证在任何时候都能及时响应请求,无论系统是否正在处理其他请求或是否发生故障。
  3. 分区容错性(Partition tolerance) :分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。即,系统应该能够容忍网络分区,即使部分节点之间的通信被中断,系统仍然能够继续运行并提供服务。

注意:CAP原则指出,在分布式系统中,这三个属性不能同时满足,最多只能同时满足其中的两个。这是因为当网络分区发生时,系统需要在一致性和可用性之间进行权衡。如果选择保持一致性(C),那么在分区发生时,系统可能需要拒绝一些请求以保证数据的一致性,这会影响系统的可用性(A)。如果选择保持可用性(A),那么在分区发生时,系统可能会接受并处理一些可能导致数据不一致的请求。

1.2. BASE(Basically Available, Soft-state, Eventually Consistent)

BASE理论是对CAP中一致性和可用性权衡的结果,它起源于对大规模互联网系统分布式实践的总结,并基于CAP定理逐渐演化而来。BASE理论包括三个核心要素:

  1. 基本可用(Basically Available) :系统应该能够在大多数情况下正常工作并提供服务,即使发生了一些故障或错误。这意味着系统应该能够容忍一些非关键性的故障,并在故障发生时保持部分功能的可用性。
  2. 软状态(Soft-state) :允许系统中的数据存在中间状态(即CAP理论中的数据不一致),并认为该中间状态不会影响系统的整体可用性。即,系统可以允许数据在不同节点之间存在一定的延迟或不一致性,但最终应该能够达到一致的状态。
  3. 最终一致性(Eventually Consistent) :强调系统中所有的数据副本在经过一段时间的同步后,最终能够达到一个一致的状态。这与强一致性不同,强一致性要求在任何时刻,系统中的所有���据副本都应该是相同的。而最终一致性则允许在短时间内存在不一致性,但系统应该能够保证在最终状态下所有副本的数据都是一致的。

2. 搭建分布式事务管理器

下面我们来搭建一下 tx-lcn 这个分布式事务框架。在这个框架中,它将事务管理器称为 协调者,也叫 tm,每个参与事务的叫做参与者,也叫 tc。下面我们就来简述一下这两者的搭建,另外这个是它的官网:CodingApi | CodingAPI is an open source organization.

2.1. TM 搭建

首先导入依赖,我们的项目是基于 springboot 来搭建的,另外 tx-lcn 使用到了数据库和 redis,其中数据库需要我们自己导入,因为数据库有很多,而 redis 只有一个。

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

<dependency>
    <groupId>com.codingapi.txlcn</groupId>
    <artifactId>txlcn-tm</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>

然后我们需要创建一个数据库,以及一张表,建库建表语句 tx-lcn 的 jar 包也有,官网也有,这里我就直接引用 jar 包中的语句,他使用的是 mysql。

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;

然后就是配置文件了,这个配置文件经过我的尝试,发现 yml 的配置文件,tx-lcn 读取不了,只能读取 properties 的配置文件。配置可参考官网的配置,下面是我的配置:

# tx-manager 服务端口
server.port=23456
spring.application.name=tx-manager
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimeZone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=12345
spring.jpa.database-platform=org.hibernate.dialect.MySQL57Dialect
spring.jpa.hibernate.ddl-auto=update
spring.redis.host=localhost
spring.redis.database=0
spring.redis.port=6379
tx-lcn.logger.enabled=true
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=UTC&useSSL=false
tx-lcn.logger.username=root
tx-lcn.logger.password=12345
# TC 连接端口
tx-lcn.manager.port=8070
tx-lcn.manager.admin-key=12345
tx-lcn.manager.ex-url-enabled=false
tx-lcn.manager.seq-len=12

注意上面的 server.porttx-lcn.manager.port 这两个端口的作用可不一样,前者是供浏览器那样的用户终端访问的,有 UI,可以通过 localhost:port 来访问,查看 TC 的情况。后者是 TC 连接以及传输数据的端口。

最后在启动类上加上 @EnableTransactionManagerServer 注解即可。

2.2. TC 搭建

首先是安装依赖:

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

然后是配置文件,添加下面的配置:

tx-lcn:
  client:
    manager-address: localhost:8070

然后在你的事务方法上加上下面的注解。

@Transactional
@LcnTransaction

最后在启动类上添加 @EnableDistributedTransaction 注解即可。

2.3. 测试

同时使用熔断器和分布式事务 @LcnTransaction,经过测试,两个事务方法,如果后者出现了错误,两者都会触发回滚。熔断器也能正常触发。不过有些情况下熔断器和分布式事务一起使用会有问题,后面我们再细说。

@Transactional
@LcnTransaction
@HystrixCommand(fallbackMethod = "fallback", commandProperties = {
    @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
})
转载自:https://juejin.cn/post/7385776177716936730
评论
请登录