日期:2014-05-16  浏览次数:20646 次

一个简单的跨域跨数据库事务处理架构

?

原来只是有点这个想法,怎么去做这个事务,这次给公司做新架构演示,随带就加进去了,居然还成了,还像那么回事:

我的做法很简单:自己写了个事务处理类,提供一个静态的启动事务方法,然后就是Commit,Rollback方法,再利用GUID作为事务ID。有事务处理类管理本地数据库链接和远程跨域服务信息,利用这些信息在Commit或者rollback时进行提交或者回滚,在数据库级上并行执行命令,需要对远程跨域提交或者回滚的,结合一个远程事务池、远程事务服务类和远程事务服务调用代理类(就提交和回滚两个方法)进行处理,其中用事务ID贯穿始终。当然,所有的数据访问层,数据库访问层都来由一个事务类参数,没有事务的话就为空。由逻辑处理层决定是否采用事务处理。做的就这么简单,结果感觉还可以;当然这个模式有个致命的弱点,就是无法解决Commit一致性问题,就是如果涉及到多个数据库时,如果前N-1个数据库服务都提交成功,第N个数据库提交失败就没办法了。在跨区域事务方面问题比较大,但如果是局域网还是可以的。这种方式比较适合数据分布存储(非镜像)的情况,当然,数据分割的时候需要将大部分的操作都集中在一个中心,毕竟跨区域访问还是有些慢得。

这次整得这个架构,可以分布式查询,同时更新多个数据库(可以控制到表级),并对业务逻辑层透明,速度和易用性感觉都还不错,而且业务层处理事务的时候可以支持搭积木方式进行。

这个架构带有云应用架构的味道,可以分业务,分用户存放数据,应用部分也可以支持多中心,多负载方式,理论上来讲扩展性无限。当然,因为主要的目的不是做镜像同步支持,所以我没有加入数据库命令队列处理方式来保证可靠性,在数据库节点方面只是简单的采用了同时更新3份,查询则随机选其中一份的方式。对于企业级业务,特别是高实时性和一致性的应用,如果跨数据库,事务处理和可靠性保证要一起做,真的很难。所以后来放弃了自己做可靠性那部分(就是同时写3份,随机读一份那部分功能),让数据库自己去做,毕竟他们更专业。

这个架构主要技术点:多线程(实现不同目标数据库查询异步进行),ODPNet,WCF(跨域访问),事务,同步(简单的采用Lock),反射机制,泛型等.

是不是很简单?但确实可用!

补充1)为什么说商业(企业)应用业务系统的事务处理非常困难呢,因为这些应用中的业务逻辑复杂,业务之间的关系非常紧密,而且是有时序性的,即业务逻辑执行是有顺序的,反映到数据库上就是其SQL语句只能一条条按进来的顺序来执行,并不能实现并行处理,因此所谓的延迟一致性(就是只保证最终结果对,不保证中间过程中也是一致的)在这里原则上是不允许的,但一般互联网应用却是可以的,比如CSDN的点击次数统计,博客排名等,用户并不会在意某一点上的排名准确性,而只要基于增量更新原则,虽然不能保证实时准确,但可以保证最终准确性?。在事务隔离级别上,为保证业务逻辑的正确,理论上应该是隔离级别越高越好,但隔离级别太高,数据库的压力就会非常大,但至少要保证不读赃数据。这带来的问题就是数据库对事务中的数据集的操作行(包括事务中查询语句的结果行)起码做行级锁定,?这就会导致其它很多SQL的执行如果涉及到前面事务处理中的数据,只能等待。另外,由于业务逻辑执行的时序性要求,也会导致很多操作结果的提交是不可逆的,这在ERP的物料需求分析体现最为明显。因此要保证业务数据库的性能,事务是一定要少用的。一个数据库如此,多个数据库,或者是跨域应用就更麻烦,更困难了。

对于火车票售票系统,最好的办法就是从应用和分割数据上去细分处理,而且也非常困难,因为还涉及到老系统的兼容。正如有网友说的,拿互联网应用的思维去思考业务应用系统最多只能是借鉴。

?

补充2) 如图:

?

如上图,如果是事务,如果是本地访问,只要在第一次执行事务命令时创建连接,并在连接上开始事务,并将这个连接和事务添加到事务类实例的连接列表中,第二次本地执行时,因为有连接和事务,就不需要在创建了,直接利用已有的连接和事务执行SQL命令,如果需要跨域访问,同样需要在事务记下访问日志,这样就可以根据本地连接池和远程访问日志做提交和回滚。当然,也会有远程事务提交和回滚的服务。在系统中保持一个远程事务池,并提供远程提交和回滚服务,同样的,如果一个远程调用过来时,如果事务参数有效,一样遵循第一次创建一个事务实例,并放入远程事务池中,后面的执行就直接调用对应的数据访问接口层执行命令即可(需要注意防止跨域死循环调用);如果接到远程提交或者回滚,只要调出远程事务池中的事务实例,调用其提交或回滚方法即可。

更多信息请查看?java进阶网?http://www.javady.com/index.php/category/thread