共计 2566 个字符,预计需要花费 7 分钟才能阅读完成。
Distributed Transaction Processing: Reference Model
Distributed Transaction Processing: The XA Specification
1、事务简介
事务 (Transaction) 是拜访并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组 SQL 语句组成。事务应该具备 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 个性。
原子性(atomicity):个事务是一个不可分割的工作单位,事务中包含的诸操作要么都做,要么都不做。
一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务的中间状态不能被察看到的。
隔离性(isolation):一个事务的执行不能被其余事务烦扰。即一个事务外部的操作及应用的数据对并发的其余事务是隔离的,并发执行的各个事务之间不能相互烦扰。隔离性又分为四个级别:读未提交(read uncommitted)、读已提交(read committed,解决脏读)、可反复读(repeatable read,解决虚读)、串行化(serializable,解决幻读)。
持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的扭转就应该是永久性的。接下来的其余操作或故障不应该对其有任何影响。
任何事务机制在实现时,都应该思考事务的 ACID 个性,包含:本地事务、分布式事务。
2 本地事务
大多数场景下,咱们的利用都只须要操作繁多的数据库,这种状况下的事务称之为本地事务(Local Transaction)。本地事务的 ACID 个性是数据库间接提供反对。本地事务利用架构如下所示:
在 JDBC 编程中,咱们通过 java.sql.Connection 对象来开启、敞开或者提交事务。代码如下所示:
代码块
Plain Text
Connection conn = … // 获取数据库连贯
conn.setAutoCommit(false); // 开启事务
try{
//… 执行增删改查 sql
conn.commit(); // 提交事务
}catch (Exception e) {
conn.rollback();// 事务回滚
}finally{
conn.close();// 敞开链接
}
此外,很多 java 利用都整合了 spring,并应用其申明式事务管理性能来实现事务性能。个别应用的步骤如下:
1、配置事务管理器。spring 提供了一个 PlatformTransactionManager 接口,其有 2 个重要的实现类:
DataSourceTransactionManager:用于反对本地事务,事实上,其外部也是通过操作 java.sql.Connection 来开启、提交和回滚事务。
JtaTransactionManager:用于反对分布式事务,其实现了 JTA 标准,应用 XA 协定进行两阶段提交。须要留神的是,这只是一个代理,咱们须要为其提供一个 JTA provider,个别是 Java EE 容器提供的事务协调器(Java EE server’s transaction coordinator),也能够不依赖容器,配置一个本地的 JTA provider。
2、在须要开启的事务的 bean 的办法上增加 @Transitional 注解
能够看到,spring 除了反对本地事务,也反对分布式事务,上面咱们先对分布式事务的典型利用场景进行介绍。
3 分布式事务典型场景
当下互联网倒退热火朝天,绝大部分公司都进行了数据库拆分和服务化(SOA)。在这种状况下,实现某一个业务性能可能须要横跨多个服务,操作多个数据库。这就波及到到了分布式事务,用须要操作的资源位于多个资源服务器上,而利用须要保障对于多个资源服务器的数据的操作,要么全副胜利,要么全副失败。实质上来说,分布式事务就是为了保障不同资源服务器的数据一致性。
3.1、跨库事务
跨库事务指的是,一个利用某个性能须要操作多个库,不同的库中存储不同的业务数据。笔者见过一个绝对比较复杂的业务,一个业务中同时操作了 9 个库。下图演示了一个服务同时操作 2 个库的状况:
3.2 分库分表
通常一个库数据量比拟大或者预期将来的数据量比拟大,都会进行程度拆分,也就是分库分表。如下图,将数据库 B 拆分成了 2 个库:
对于分库分表的状况,个别开发人员都会应用一些数据库中间件来升高 sql 操作的复杂性。如,对于 sql:insert into user(id,name) values (1,”tianshouzhi”),(2,”wangxiaoxiao”)。这条 sql 是操作单库的语法,单库状况下,能够保障事务的一致性。
然而因为当初进行了分库分表,开发人员心愿将 1 号记录插入分库 1,2 号记录插入分库 2。所以数据库中间件要将其改写为 2 条 sql,别离插入两个不同的分库,此时要保障两个库要不都胜利,要不都失败,因而基本上所有的数据库中间件都面临着分布式事务的问题。
3.3 服务化(SOA)
微服务架构是目前一个比拟一个比拟火的概念。例如下面笔者提到的一个案例,某个利用同时操作了 9 个库,这样的利用业务逻辑必然非常复杂,对于开发人员是极大的挑战,应该拆分成不同的独立服务,以简化业务逻辑。拆分后,独立服务之间通过 RPC 框架来进行近程调用,实现彼此的通信。下图演示了一个 3 个服务之间彼此调用的架构:
Service A 实现某个性能须要间接操作数据库,同时须要调用 Service B 和 Service C,而 Service B 又同时操作了 2 个数据库,Service C 也操作了一个库。须要保障这些跨服务的对多个数据库的操作要不都胜利,要不都失败,实际上这可能是最典型的分布式事务场景。
小结:上述探讨的分布式事务场景中,无一例外的都间接或者间接的操作了多个数据库。如何保障事务的 ACID 个性,对于分布式事务实现计划而言,是十分大的挑战。同时,分布式事务实现计划还必须要思考性能的问题,如果为了严格保障 ACID 个性,导致性能重大降落,那么对于一些要求疾速响应的业务,是无奈承受的。