龙空技术网

shardingjdbc-分布式事务实战案例

程序员小胡 105

前言:

如今你们对“java分布式项目案例分享报告”大致比较关切,我们都想要了解一些“java分布式项目案例分享报告”的相关知识。那么小编同时在网络上搜集了一些关于“java分布式项目案例分享报告””的相关内容,希望小伙伴们能喜欢,兄弟们一起来了解一下吧!

详细请参考官方文档:分布式事务 :: ShardingSphere

首先确定好自身引入的shradingjdbc版本号,因为我用的它的starter版本,所以没用这种core包的版本,所以yml配置还有分布式事务的配置也不尽相同,此处我以starter版本为阐述。

<!-- -不要使用RC1 (Release Candidate)供大家测试版本 --><dependency>    <groupId>org.apache.shardingsphere</groupId>    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>    <version>4.0.0</version> </dependency>
<dependency>    <groupId>org.apache.shardingsphere</groupId>    <artifactId>sharding-jdbc-core</artifactId>    <version>${latest.release.version}</version></dependency>

此外支持跨库事务必须配置对应的事务管理器的bean

package com.mode.technology.config; import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.PlatformTransactionManager;import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; @Configuration@EnableTransactionManagementpublic class TransactionConfiguration {     @Bean    public PlatformTransactionManager txManager(final DataSource dataSource) {        return new DataSourceTransactionManager(dataSource);    }}
核心概念两阶段事务-XA

两阶段事务提交采用的是X/OPEN组织所定义的DTP模型,通过抽象出来的AP, TM, RM的概念可以保证事务的强一致性。 其中TMRM间采用XA的协议进行双向通信。 与传统的本地事务相比,XA事务增加了prepare阶段,数据库除了被动接受提交指令外,还可以反向通知调用方事务是否可以被提交。 因此TM可以收集所有分支事务的prepare结果,最后进行原子的提交,保证事务的强一致性。

Java通过定义JTA接口实现了XA的模型,JTA接口里的ResourceManager需要数据库厂商提供XA的驱动实现,而TransactionManager则需要事务管理器的厂商实现,传统的事务管理器需要同应用服务器绑定,因此使用的成本很高。 而嵌入式的事务管器可以以jar包的形式提供服务,同ShardingSphere集成后,可保证分片后跨库事务强一致性。

通常,只有使用了事务管理器厂商所提供的XA事务连接池,才能支持XA的事务。ShardingSphere整合XA事务时,分离了XA事务管理和连接池管理,这样接入XA时,可以做到对业务的零侵入。

实现原理查看官网文档:

Saga事务

Saga这个概念来源于三十多年前的一篇数据库论文Sagas ,一个Saga事务是一个有多个短时事务组成的长时的事务。 在分布式事务场景下,我们把一个Saga分布式事务看做是一个由多个本地事务组成的事务,每个本地事务都有一个与之对应的补偿事务。在Saga事务的执行过程中,如果某一步执行出现异常,Saga事务会被终止,同时会调用对应的补偿事务完成相关的恢复操作,这样保证Saga相关的本地事务要么都是执行成功,要么通过补偿恢复成为事务执行之前的状态。

自动反向补偿

Saga定义了一个事务中的每个子事务都有一个与之对应的反向补偿操作。由Saga事务管理器根据程序执行结果生成一张有向无环图,并在需要执行回滚操作时,根据该图依次按照相反的顺序调用反向补偿操作。Saga事务管理器只用于控制何时重试,何时补偿,并不负责补偿的内容,补偿的具体操作需要由开发者自行提供。

ShardingSphere采用反向SQL技术,将对数据库进行更新操作的SQL自动生成反向SQL,并交由saga-actuator执行,使用方则无需再关注如何实现补偿方法,将柔性事务管理器的应用范畴成功的定位回了事务的本源——数据库层面。

Seata柔性事务

Seata是阿里集团和蚂蚁金服联合打造的分布式事务框架,截止到0.5.x版本包含了AT事务和TCC事务。其中AT事务的目标是在微服务架构下,提供增量的事务ACID语意,让用户像使用本地事务一样,使用分布式事务,核心理念同ShardingSphere一脉相承。

Seata AT事务模型

Seata柔性事务

Seata是阿里集团和蚂蚁金服联合打造的分布式事务框架,截止到0.5.x版本包含了AT事务和TCC事务。其中AT事务的目标是在微服务架构下,提供增量的事务ACID语意,让用户像使用本地事务一样,使用分布式事务,核心理念同ShardingSphere一脉相承。

Seata AT事务模型

Seata AT事务模型包含TM(事务管理器),RM(资源管理器),TC(事务协调器)。其中TC是一个独立的服务需要单独部署,TM和RM以jar包的方式同业务应用部署在一起,它们同TC建立长连接,在整个事务生命周期内,保持RPC通信。 其中全局事务的发起方作为TM,全局事务的参与者作为RM ; TM负责全局事务的begin和commit/rollback,RM负责分支事务的执行结果上报,并且通过TC的协调进行commit/rollback。

支持功能

本地事务

功能

完全支持非跨库事务,例如:仅分表,或分库但是路由的结果在单库中。完全支持因逻辑异常导致的跨库事务。例如:同一事务中,跨两个库更新。更新完毕后,抛出空指针,则两个库的内容都能回滚。不支持因网络、硬件异常导致的跨库事务。例如:同一事务中,跨两个库更新,更新完毕后、未提交之前,第一个库宕机,则只有第二个库数据提交。

支持情况

Sharding-JDBC和Sharding-Proxy原生支持本地事务(无需引入其它依赖)

测试新增

我这三个sql会根据zone字段落到不同的库,执行此接口发现数据库没有新增数据,说明事务确实回滚了

@ApiOperation(value = "测试分库分表插入-分布式事务-本地事务")@GetMapping("/addTransactional")@Transactional(rollbackFor = Exception.class)public Tip<Void> addTransactional() {    TOrder orderBJ = new TOrder();    orderBJ.setUserId(100);    orderBJ.setZone("bj");    torderDao.insertSelective(orderBJ);    TOrder orderSH = new TOrder();    orderSH.setUserId(100);    orderSH.setZone("sh");    torderDao.insertSelective(orderSH);    TOrder orderSZ = new TOrder();    orderSZ.setUserId(100);    orderSZ.setZone("sz");    torderDao.insertSelective(orderSZ);      int a= 1/0;    return TipUtil.success();}
二阶段事务-XA

ShardingSphere默认的XA事务管理器为Atomikos,在项目的logs目录中会生成xa_tx.log, 这是XA崩溃恢复时所需的日志,请勿删除。也可以通过在项目的classpath中添加jta.properties来定制化Atomikos配置项。具体的配置规则请参考Atomikos的官方文档。

功能

支持数据分片后的跨库XA事务两阶段提交保证操作的原子性和数据的强一致性服务宕机重启后,提交/回滚中的事务可自动恢复SPI机制整合主流的XA事务管理器,默认Atomikos,可以选择使用Narayana和Bitronix同时支持XA和非XA的连接池提供spring-boot和namespace的接入端

不支持项

服务宕机后,在其它机器上恢复提交/回滚中的数据

需要引入对应的pom包

<dependency>    <groupId>org.apache.shardingsphere</groupId>    <artifactId>sharding-transaction-xa-core</artifactId>    <version>4.0.0</version></dependency>

两阶段提交主要的原理是以上面的请求业务为例,当整个业务完成了之后只是第一阶段提交,在第二阶段提交之前会检查其他所有事务是否已经提交,如果前面出现了错误或是没有提交,那么第二阶段就不会提交,而是直接rollback操作,这样所有的事务都会做Rollback操作。上面的案例也可以通过二阶段xa事务来管理,改写下,相比第一种它对于容灾,务宕机重启后,它依然会提交/回滚中事务,可自动恢复

  @ApiOperation(value = "测试分库分表插入-分布式事务-xa事务")    @GetMapping("/addTransactional")    @Transactional(rollbackFor = Exception.class)    @ShardingTransactionType(value = TransactionType.XA)    public Tip<Void> addTransactional() {        TOrder orderBJ = new TOrder();        orderBJ.setUserId(100);        orderBJ.setZone("bj");        torderDao.insertSelective(orderBJ);        TOrder orderSH = new TOrder();        orderSH.setUserId(100);        orderSH.setZone("sh");        torderDao.insertSelective(orderSH);        TOrder orderSZ = new TOrder();        orderSZ.setUserId(100);        orderSZ.setZone("sz");        torderDao.insertSelective(orderSZ);        int a= 1/0;        return TipUtil.success();    }

上述基于XA协议的全局事务,是属于强一致性事务,因为在全局事务中,只要有任何一个RM出现异常,都会导致全局事务回滚。同时,本地事务在Prepare阶段锁定资源时,如果有其他事务要要修改相同的数据,就必须要等待前面的事务完成,这本身是无可厚非的设计,但是由于多个RM节点是跨网络,一旦出现网络延迟,就导致该事务一直占用资源使得整体性能下降。所以它不适用于对并发有要求的情况

另外,在XA COMMIT阶段,如果其中一个RM因为网络超时没有收到数据提交的指令,会导致数据不一致,为了解决这个问题,很多开源分布式事务框架都会提供重试机制来保证数据一致性。

柔性事务-saga完全支持跨库事务支持失败SQL重试及最大努力送达支持反向SQL、自动生成更新快照以及自动补偿默认使用关系型数据库进行快照及事务日志的持久化,支持使用SPI的方式加载其他类型的持久化

不支持项

暂不支持资源隔离暂不支持服务宕机后,自动恢复提交中的commit和rollback

支持情况

ShardingSphere的柔性事务已通过第三方SPI实现Saga事务,Saga引擎使用Servicecomb-Saga。

注意

反向SQL需要主键,请确保在表结构中定义主键对于INSERT语句, 需要在SQL中显示插入主键值,如INSERT INTO ${table_name} (id, value, ...) VALUES (11111, '', ....) (其中id为表主键)若需要自动生成主键,可使用ShardingSphere的分布式主键。

实现原理官网参考:

柔性事务-seta

功能

完全支持跨库分布式事务支持RC隔离级别通过undo快照进行事务回滚支持服务宕机后的,自动恢复提交中的事务

依赖

需要额外部署Seata-server服务进行分支事务的协调

待优化项

ShardingSphere和Seata会对SQL进行重复解析

实现原理官网参考:

结尾

对于sega和seta这两种柔性事务的处理,我目前工作中还没遇到过,如果真的要用我肯定会优先看下阿里的seta框架,将它集成到我们项目中。

标签: #java分布式项目案例分享报告