Java事务学习一

 

最近工作中遇到了这样一个问题,使得我不得不开启自己计划已久的事务学习计划了。

 

问题是这个样子的:

 

java去掉事务查询 java 事务_java去掉事务查询

 

如上图所示,我们从external queue中读取message,然后交给internal queue,再由internal queue更新到数据库。

 

其中,external queue采用的是IBM MQ,而internal queue则是Tomcat内部的JMS queue。由于二者不在同一台服务器上并且是不同类型的data source,需要一个XA transaction Manager来进行全局的分布式事务管理;同理,internal queue和数据库之间也需要用XA transaction Manager。

 

问题出现了。什么问题呢?

第一、事务管理的问题。当消息从internal queue更新到数据库时,杂乱在更新成功的情况下,internal queue中的消息并没有被移除;这导致了会有重复的message内容被更新到数据库。

第二、JDBC connection pool的问题。当前采用的connection pool不提供以下特性:验证该connection pool中的connection是否有效,如果无效,则移除。由此引起的问题是,当该connection pool中存在无效connection时,不会被移除,而是反复的被client从该connection pool中取出,从而导致应用出现问题。

 

哇啦啦,终于把问题交代完啦。

 

据说,某菲在看这个问题描述的时候,单单从问题描述中,就一条一条的揪出来十个需要学习的点(而且还木有发散)。

 

于是,我深深的认识到了学习事务的决定不能再拖下去了!于是,我又从杂乱的download文件夹中找出了那本《Java transaction design strategy》

 

于是…便有了下面的内容。

 

首先,补一下基本概念:

1. JDBC connection pool:

这个叫做JDBC connection pool的池子和所有的池子都差不多,就是存放了很多很多的JDBC connection。

 

和其他池子的管理规定也差不多,client可以从这个池子借走一根JDBC connection,然后用,用完了之后再还回来。

 

使用池子的好处和目的也差不多,就是在有多用户的情况下更加灵活有效地调到资源。

 

学术一点:

 

java去掉事务查询 java 事务_java去掉事务查询_02

 

 

client会在JNDI Tree上查找data source,这个JNDI tree上的每个data source 都会从connection pool里面找connection,然后connection pool会让JDBC driver创建数据库的物理连接。

 

client分为internal client和external client,分别表示这个client在server的内部或者外部。

 

关于JDBC connection pool的小故事就先讲到这里。这里是最基本的基本知识,接下来我们就聊一下对于这个问题的解决方案,我们希望采用的Tomcat JDBC connection pool,当然他具备所有上述JDBC connection pool的基本特性,同时又有自身的独特优势。

 

2. Tomcat JDBC connection pool

 

上面提到我们决定采用Tomcat JDBC connection pool作为解决那个JDBC connection pool没有对无效connection做检测的问题。

 

这是因为Tomcat提供了这种特性:可以在从connection池子中借connection以及还connection之前,以及任何时候对connection是否有效健康进行检测,如果是不健康的,那么就会从这个connection池子中丢出去。

 

比如Tomcat JDBC connection pool提供了以下几个属性提供可配置的connection体检:

1) testOnBorrow:布尔值;用于配置connection池子是否会在借出去某个connection之前对其进行体检。如果体检不通过,池子就会把这个connection丢弃,并且试图借另一个connection出去。

 

那么池子君又是怎样对connection做体检的呢?

汤姆凯特家的池子还提供了这样一条属性:

1)validationQuery: String;池子就是通过运行这样一条SQL 语句来检查某根connection是否为正常的。通常会用“select 1”。

 

所以说嘛,我们可以用汤姆凯特家的JDBC connection pool去解决我们的问题。

 

3. XA

问题描述中反反复复的出现几个词:XA,XA-compliance,2-phase commit,1.5-phase commit。到底是什么意思呀?

 

首先XA,某师父说XA就是global或者global transaction,就是这么简单。那么全局事务是相对于局部事务的概念,分别对应于分布式系统的事务管理和单机事务管理。

 

举一个最简单的 分布式事务管理的例子,就是我们希望从一条queue中读出一个消息,然后更新到数据库中。

 

某师父还说,XA就等同于2-phase commit

 

XA-compliance就是说某个resource是遵循XA规范的。

 

扫噶!

 

那么什么是2-phase commit呢?这个也挺有意思的,就放在我的第四条吧:)

 

4. 2-phase commit(两阶段提交)

两阶段提交的 意思其实很好理解,就是把整个的事务提交过程分为两个阶段。

第一阶段称为等待提交与投票阶段:就是有一个中央调度员,等着他所管理的分布式事务系统中的各个同学完成他们的任务,等待他们传回自己各自的结果:或者提交,或者回滚。至此,第一阶段完成。

 

第二阶段称为统一提交阶段:中央调度员根据他收到的投票结果,做出最初决定,是否提交或者回滚,并且把该决策告知该分布式管理系统中的所有同学,然后这些同学们无论自己的执行结果是什么,都要服从中央的调度,该提交提交,该回滚回滚。

 

好啦,先写到这里吧,我要回家啦,哈哈!