篇首语:本文由编程笔记#自由互联小编为大家整理,主要介绍了Sharding JDBC 实战:分布式事务处理相关的知识,希望对你有一定的参考价值。
点击关注公众号实用技术文章及时了解
在我们使用Sharding JDBC分库分表的时候会带来另外一个问题就是分布式事务问题如下图所示。用户采购商品业务整个业务包含3个微服务
库存服务: 扣减给定商品的库存数量。
订单服务: 根据采购请求生成订单。
账户服务: 用户账户金额扣减。
这三个业务操作应该属于同一个事务但是这些数据却分配在不同的数据库上所以没办法采用数据库的事务来保证数据一致性。
这个时候要解决分布式事务问题就需要引入全局事务。
1. 什么是全局事务呢
全局事务是一个DTP模型的事务所谓DTP模型指的是 X/Open DTP (X/Open Distributed Transaction Processing Reference Model)是 X/Open 这个组织定义的一套分布式事务的标准。
X/Open即现在的open group是一个独立的组织主要负责制定各种行业技术标准。
官网地址http://www.opengroup.org/
X/Open组织主要由各大知名公司或者厂商进行支持这些组织不光遵循X/Open组织定义的行业技术标准也参与到标准的制定。
X/Open了定义了规范和API接口由这个厂商进行具体的实现这个标准提出了使用二阶段提交(2PC –Two-Phase-Commit)来保证分布式事务的完整性。后来J2EE也遵循了X/OpenDTP规范设计并实现了java里的分布式事务编程接口规范-JTA如下图所示表示一个X/Open DTP模型。
X/Open DTP模型定义了三个角色和两个协议其中三个角色分别如下
APApplication Program表示应用程序也可以理解成使用DTP模型的程序
RMResource Manager资源管理器这个资源可以是数据库 应用程序通过资源管理器对资源进行控制资源管理器必须实现XA定义的接口
TMTransaction Manager表示事务管理器负责协调和管理全局事务事务管理器控制整个全局事务管理事务的生命周期并且协调资源。
两个协议分别是
XA协议 XA 是X/Open DTP定义的资源管理器和事务管理器之间的接口规范TM用它来通知和协调相关RM事务的开始、结束、提交或回滚。
目前Oracle、mysql、DB2都提供了对XA的支持XA接口是双向的系统接口在事务管理器(TM ) 以及多个资源管理器之间形成通信的桥梁XA不能自动 提交
https://dev.mysql.com/doc/refman/8.0/en/xa.html
https://dev.mysql.com/doc/refman/8.0/en/xa-statements.html
XA协议的语法主流的数据库都支持 XA协议从而能够实现跨数据库事务。
XA START|BEGIN xid [JOIN|RESUME] --负责开启或者恢复一个事务分支并且管理XID 到调用线程 XA END xid [SUSPEND [FOR MIGRATE]] --负责取消当前线程与事务分支的关联 XA PREPARE xid --负责询问RM 是否准备好了提交事务分支 XA COMMIT xid [ONE PHASE] --知RM提交事务分支 XA ROLLBACK xid --通知RM回滚事务分支 XA RECOVER [CONVERT XID]
TX协议 全局事务管理器与资源管理器之间通信的接口
在分布式系统中每一个机器节点虽然都能够明确知道自己在进行事务操作过程中的结果是成功还是失败但却无法直接获取到其他分布式节点的操作结果。
因此当一个事务操作需要跨越多个分布式节点的时候为了保持事务处理的ACID特性就需要引入一个“协调者”TM来统一调度所有分布式节点的执行逻辑这些被调度的分布式节点被称为AP。TM负责调度AP的行为并最终决定这些AP是否要把事务真正进行提交到RM。
2. 2pc提交协议
在X/OpenDTP模型中一个分布式事务所涉及的SQL逻辑都执行完成并到了RM要最后提交事务的关键时刻为了避免分布式系统所固有的不可靠性导致提交事务意外失败TM 果断决定实施两步走的方案这个就称为二阶提交如下图所示。
二阶段提交是计算机网络尤其是在数据库领域内为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的一种算法。通常二阶段提交协议也被认为是一种一致性协议用来保证分布式系统数据的一致性。
目前绝大部分的关系型数据库都是采用二阶段提交协议来完成分布式事务处理的利用该协议能够非常方便地完成所有分布式事务AP的协调统一决定事务的提交或回滚从而能够有效保证分布式数据一致性因此2pc也被广泛运用在许多分布式系统中。
3. XA事务存在的问题
上述基于XA协议的全局事务是属于强一致性事务因为在全局事务中只要有任何一个RM出现异常都会导致全局事务回滚。同时本地事务在Prepare阶段锁定资源时如果有其他事务要要修改相同的数据就必须要等待前面的事务完成这本身是无可厚非的设计但是由于多个RM节点是跨网络一旦出现网络延迟就导致该事务一直占用资源使得整体性能下降。
另外在XA COMMIT阶段如果其中一个RM因为网络超时没有收到数据提交的指令会导致数据不一致为了解决这个问题很多开源分布式事务框架都会提供重试机制来保证数据一致性。
4. CAP理论
说到强一致性的问题必然要提到CAP理论。
CAP的含义
CConsistency 一致性 同一数据的多个副本是否实时相同。
AAvailability 可用性 可用性一定时间内 Partition tolerance 分区容错性 将同一服务分布在多个系统中从而保证某一个系统宕机仍然有其他系统提供相同的服务。
CAP理论告诉我们在分布式系统中C、A、P三个条件中我们最多只能选择两个。那么问题来了究竟选择哪两个条件较为合适呢
对于一个业务系统来说分区容错性是必须要满足的条件。业务系统之所以使用分布式系统主要原因有两个
提升整体性能 当业务量猛增单个服务器已经无法满足我们的业务需求的时候就需要使用分布式系统使用多个节点提供相同的功能从而整体上提升系统的性能这就是使用分布式系统的第一个原因。
实现分区容错性 单一节点 或 多个节点处于相同的网络环境下那么会存在一定的风险万一该机房断电、该地区发生自然灾害那么业务系统就全面瘫痪了。为了防止这一问题采用分布式系统将多个子系统分布在不同的地域、不同的机房中从而保证系统高可用性。
所以我们需要根据自己的业务需求选择采取CP还是AP。
5. Sharding-JDBC分布式事务支持
了解了X/Open DTP模型的全局事务解决方案就必然需要一个成熟的技术中间件来简化我们对于分布式事务的开发逻辑而Sharding-JDBC提供了分布式事务解决方案。
Sharding-JDBC支持以下四种事务模型实际上这些分布式事务模式都是集成开源的事务组件做的集成。
Atomikos事务
Narayana事务
Bitronix事务
Seata事务
Apache ShardingSphere 默认的 XA 事务管理器为 Atomikos下面我们通过Atomikos来配置一个分布式事务的使用模型。
5.1 Atomikos事务
Atomikos是为Java平台提供的开源的事务管理工具它包含收费和开源两个版本开源版本基本能满足我们的需求。
Atomikos实现了JTA/XA规范中的事务管理器(Transaction Manager)应该实现的相关接口。
JTA即Java Transaction APIJTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据JDBC驱动程序的JTA支持极大地增强了数据访问能力。
TransactionManager : 常用方法可以开启、回滚、获取事务。begin(),rollback()…
XAResouce : 资源管理通过Session来进行事务管理。commit(xid)…
XID : 每一个事务都分配一个特定的XID
JTA是如何实现多数据源的事务管理呢?
主要的原理是两阶段提交以上面的请求业务为例当整个业务完成了之后只是第一阶段提交,在第二阶段提交之前会检查其他所有事务是否已经提交如果前面出现了错误或是没有提交那么第二阶段就不会提交而是直接rollback操作这样所有的事务都会做Rollback操作。
5.2 实战
5.2.1 项目搭建
使用IDEA直接创建Spring boot 项目即可。
5.2.2 依赖
由于使用XA事务所以除了Sharding依赖外还需要引入事务依赖。
org.apache.shardingsphere shardingsphere-jdbc-core-spring-boot-starter 5.0.0-alpha com.zaxxer HikariCP 3.4.2 org.freemarker freemarker org.apache.shardingsphere shardingsphere-transaction-xa-core 5.0.0-alpha
5.2.3 配置
接下来就是配置相关数据库连接信息以及分片规则
在这里主要做的是创建了两个数据源数据源最好设置两台服务器的数据库以及设置好了相应的分库规则。
server.port8080spring.mvc.view.prefixclasspath:/templates/spring.mvc.view.suffix.htmlspring.shardingsphere.props.sql-showtruespring.shardingsphere.datasource.names"ds-0,ds-1"spring.shardingsphere.datasource.common.typecom.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.common.driver-class-namecom.mysql.jdbc.Driverspring.shardingsphere.datasource.ds-0.jdbc-urljdbc:mysql://localhost:3306/shard01?serverTimezoneUTCfalsetrueUTF-8spring.shardingsphere.datasource.ds-0.usernamerootspring.shardingsphere.datasource.ds-0.password123456spring.shardingsphere.datasource.ds-1.jdbc-urljdbc:mysql://localhost:3306/shard02?serverTimezoneUTCfalsetrueUTF-8spring.shardingsphere.datasource.ds-1.usernamerootspring.shardingsphere.datasource.ds-1.password123456spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-columnuser_idspring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-namedatabase-inlinespring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.typeINLINEspring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expressionds-$->user_id % 2spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.columnorder_idspring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-namesnowflakespring.shardingsphere.rules.sharding.key-generators.snowflake.typeSNOWFLAKEspring.shardingsphere.rules.sharding.key-generators.snowflake.props.worker-id123
5.2.4 事务一致性注解
Sharding jdbc解决事务一致性可以直接通过ShardingTransactionType(TransactionType.XA)注解实现我们只需要在对应的方法上加上即可。
比如下图由于我们在配置文件中是通过user_id进行分库的然后我们在这里通过随机数会根据分片规则往两个数据库中插入数据。
当i4的时候我们人为的制造异常如果我们不采用全局事务的话则之前插入的数据还会再数据库中。所以这个时候我们只需要加上ShardingTransactionType(TransactionType.XA)注解即可XA属于强一致性。
6. 项目地址
https://gitee.com/cl1429745331/sharding-jdbc-demo
来源blog.csdn.net/qq_41432730/article/
details/122373098
推荐
Java面试题宝典
技术内卷群一起来学习
PS因为公众号平台更改了推送规则如果不想错过内容记得读完点一下“在看”加个“星标”这样每次新文章推送才会第一时间出现在你的订阅列表里。点“在看”支持我们吧
【文章转自韩国多ip站群服务器 http://www.558idc.com/krzq.html处的文章,转载请说明出处】