[分布式] 分布式事务、seata
资料
文章
质量不错, 以这篇文章为主, 其他的为辅;
再有人问你分布式事务,把这篇扔给他
思路清晰, 语言简洁;
分布式事务,这一篇就够了 | 小米信息部技术团队
似乎更全面;
分布式事务最经典的七种解决方案 - SegmentFault 思否
alibaba/seata
资料
示例代码:
https://github.com/seata/seata-samples
spring-cloud快速集成
seata-samples/quick-integration-with-spring-cloud.md at master · seata/seata-samples
配置
service.vgroupMapping
事务分组
Seata 参数配置
file.conf:
service {
#transaction service group mapping
vgroupMapping.my_test_tx_group = "default"
service.vgroupMapping.my_test_tx_group
事务群组(附录1) my_test_tx_group为分组,配置项值为TC集群名
事务分组说明。
1.事务分组是什么?
事务分组是seata的资源逻辑,类似于服务实例。在file.conf中的my_test_tx_group就是一个事务分组。
2.通过事务分组如何找到后端集群?
首先程序中配置了事务分组(GlobalTransactionScanner 构造方法的txServiceGroup参数),程序会通过用户配置的配置中心去寻找service.vgroupMapping.事务分组配置项,取得配置项的值就是TC集群的名称。拿到集群名称程序通过一定的前后缀+集群名称去构造服务名,各配置中心的服务名实现不同。拿到服务名去相应的注册中心去拉取相应服务名的服务列表,获得后端真实的TC服务列表。
3.为什么这么设计,不直接取服务名?
这里多了一层获取事务分组到映射集群的配置。这样设计后,事务分组可以作为资源的逻辑隔离单位,当发生故障时可以快速failover。
上手: springcloud-jpa-seata
https://github.com/seata/seata-samples/tree/master/springcloud-jpa-seata
我的测试代码:
https://github.com/qiaoxingxing/seata-samples/tree/qxx
seata服务端docker安装
docker run --name seata-server -p 8091:8091 -p 9091:9091 seataio/seata-server:latest
localhost:9091/health
返回ok;
seataio/seata-server - Docker Image | Docker Hub
seata/Dockerfile at 17b05038870e34318e82b1eabec700c1c48cfc85 · seata/seata
mysql安装
Mysql - Official Image | Docker Hub
docker run --name mysql_local \
-e MYSQL_ROOT_PASSWORD=root123456 \
-e MYSQL_PASSWORD=root123456 \
-p 23306:3306 \
harbor.sjgs/library/mysql:5.7.30
示例代码: springcloud-jpa-seata
https://github.com/seata/seata-samples/tree/master/springcloud-jpa-seata
参考readme.md;
代码修改:
- 数据库地址
- 所有application.properties增加
spring.cloud.alibaba.seata.txServiceGroup=my_test_tx_group
- java8启动
Q&A
报错:
io.seata.common.exception.FrameworkException: No available service
事务分组配置问题;
方法1: 所有application.properties增加spring.cloud.alibaba.seata.txServiceGroup=my_test_tx_group
方法2:
所有服务改造为对应的值${spring.application.name}-fescar-service-group
:
service {
#transaction service group mapping
vgroupMapping.business-service-fescar-service-group = "default"
感想: 文档里说service.vgroupMapping
配置要"一致", 但是怎样才算是一致? 我以为是一模一样; 好的文档应该提供一个例子, 不然根本不知道他具体在说什么;
启动报错:
Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer]
jdk 1.8启动
java - Unable to instantiate default tuplizer [org.hibernate.tuple.entity.PojoEntityTuplizer] - Stack Overflow
分布式事务和数据一致性
imooc笔记: 第16周.分布式全局ID、分布式事务和数据一致性;
理论
CAP原理
C - Consistent , 一致性。 操作成功以后, 所有的节点在同一时间看到的数据都是完全一致的。
A - Availability, 可用性。 指服务一致可用, 在规定的时间内完成响应。
P - Partition tolerance , 分区容错性。 指分布式系统在遇到某节点或网络分区故障的时候, 仍然能够对外提供服务。也就是: 一个节点出错, 其他节点可以提供服务;
CAP原理指出, 这3个指标不能同时满足, 最多只能满足其中的两个。
简单理解: 分布式服务一般需要P(一个节点出错, 其他节点可以提供服务), 否则分布式没有意义; 如果要保证C, 节点间同步数据的间隙不能提供服务, 违背了A; 如果要保证A, 节点同步数据的间隙数据是不同的, 违背了C.
ACID原理
A - Atomicity(原子性) , 事务中的操作要么都做, 要么都不做。
C - Consistency(一致性) , 系统必须始终处在强一致状态下。
I - Isolation(隔离性) , 一个事务的执行不能被其他事务所干扰。
D - Durability(持久性) , 一个已提交的事务对数据库中数据的改变是永久性的。
ACID强调的是强一致性, CAP原理中, 保证的是CA, 但是在分布式系统大行其道的今天, 满足CA特性的系统很难生存下去。 ACID也逐渐的向BASE转换。
BASE原理
BASE(Basically Available、Soft State、Eventual Consistency)
Basically Available, 基本可用是指分布式系统在出现故障的时候, 允许损失部分可用性, 即保证核心可用。 比如: 电商大促时,为了应对访问量激增, 部分用户可能会被引导到降级页面, 比如为了保证下单可用, 评论无法使用.
软状态( Soft State)软状态是指允许系统存在中间状态, 而该中间状态不会影响系统整体可用性。 分布式存储中一般一份数据至少会有两到三个副本, 允许不同节点间副本同步的延时就是软状态的体现。
最终一致性( Eventual Consistency)最终一致性是指系统中的所有数据副本经过一定时间后, 最终能够达到一致的状态。 弱一致性和强一致性相反, 最终一致性是弱一致性的一种特殊情况。
BASE模型是传统ACID模型的反面,BAlSE强调牺牲高一致性, 从而获得可用性, 数据允许在一段时间内的不一致, 只要保证最终一致就可以了。
方案
XA协议的两阶段提交
原理: XA是由X/Open组织提出的分布式事务的规范,由一个事务管理器(TM)和多个资源管理器(RM)组成, 提交分为两个阶段:prepare和commit
理解: TM: java里的数据库驱动; RM: 数据库;
优缺点: 保证数据的强一致性; 效率低下,性能与本地事务相差10倍; commit阶段出现问题,事务出现不一致,需人工处理;
实现:
MySql5.7及以上均支持XA协议
MySql Connector/J5.0以上支持XA协议
Java系统中,数据源采用Atomikos
事务补偿机制
TCC(Try-Confirm-Cancel)
原理: 针对每个操作都定义一个补偿(撤销)操作, 如果执行失败就调用补偿操作;
补偿操作也有可能失败, 多次重试; 超过重试次数就记录日志, 人工处理;
优点: 逻辑清晰、流程简单
缺点: 数据一致性比XA还要差, 可能出错的点比较多; TCC属于应用层的补偿方式, 需要程序员编写大量代码. 一般不推荐使用这种方式。
演示: 视频里纯手工控制, 没有现成方案
基于本地消息表最终一致方案
BASE原理, 最终一致的实现, 允许一段时间不一致; 根据具体情况决定是否采用;
本事务之外的操作记录在消息表中, 其他事务提供操作接口; 定时轮询本地消息表, 将未执行的消息发送给操作接口; 记录操作接口执行的结果, 成功还是失败; 失败的操作设置最大失败次数, 最终失败的人工处理;
流程图:
优点: 避免了分布式事务, 实现最终一致性
缺点: 注意重试时的幂等性
基于MQ事务的最终一致方案
原理和流程与本地消息表类似;
不同点: 消息表改为MQ, 定时任务改为MQ的消费者;
流程图:
优点: MQ比定时任务更高效、可靠
缺点: MQ方案适合公司内系统(一个集群内), 不同公司无法基于MQ, 本地消息表更合适;