维护系统一致性和正确地处理错误恢复挑战的最佳方式是使用事务。数据库
一个事务就是一个复杂操做的集合,这个集合中任何一个操做的失败都会引发整个集合的失败。编程
尽管在事务进行时系统被容许暂时出于不一致的状态,可是一旦事务结束,系统必定会处于一直的状态。分布式
事务资源
事务编程须要资源(如数据库或消息队列)一块儿协做,这类资源要可以参与事务并回滚在事务中发生的变化。优化
通常状况下,咱们必须通知这些但愿执行事务性工做的资源,这个行为称为在事务中登记资源。一些资源支持自动登记,也就是说它们可以检测到自身是否被事务访问,并完成登记。资源呢一旦被登记,咱们就可以对它执行操做。若是没有错误发生,要求提交资源的全部状态发生改变;剐有错误发生,要求回滚资源的状态的全部变化。spa
在一个事务处理中,不要访问非事务的资源很关键(如文件系统),由于事务一旦被停止,是不会回滚这些非事务资源上的改变。code
事务属性
当在面向服务的应用程序中使用事务时,必须遵照四个核心属性,也就是ACID:原子性(Atomic)、一致性(Consistent)、隔离性(Isolated)和持久性(Durable)。blog
原子性
为了是事务具备原子性,当一个事务结束时,必须把对资源状态已经作的全部改变视为一个原子的,不可分割的操做。队列
当事务结束时,事务是不允许遗留任何工做在后台处理,由于这些操做违反了原子性。全部事务产生的操做必须包含在事务中。事务
事务做为一个总体,要么成功,要么失败。资源
一致性
一致性意味着事务必须是系统处于一个一致的状态。一致性和原子性不一样。即便状态的全部改变被做为一个原子操做提交了,事务也必须保证全部的改变都是一致的。
事务必须作到的就是让系统从一个一致的状态转移到另外一个一致的状态。
隔离性
隔离性意味着没有其它的实体在事务过程当中可以看到资源的状态,由于中间状态极可能是不一致的。即便中间状态是一致的,事务依然可以停止,全部的改变也能够被回滚。
参与事务的资源必须对事务所访问的数据枷锁,以防止任何其它代码的访问,同时必须在事务提交或停止取消对数据的所保护,以便其它代码能够访问。
持久性
持久性的意思是一旦成功提交,基于持久化资源(好比数据库)的数据将会被持久化,对数据的改变是永久性的。
WCF服务可以直接处理事务性的资源,并经过显式地使用编程模型(如ADO.NET)来管理事务。以下,使用这个模型,能够显式地启动和管理事务。
[ServiceContract] interface IMyContract { [OperationContract] void MyMethod(); } class MyService : IMyContract { public void MyMethod() { string connectionString = "...."; using (IDbConnection connection=new SqlConnection(connectionString)) { connection.Open(); using (IDbCommand command=new SqlCommand()) { command.Connection = connection; using (IDbTransaction transaction =connection.BeginTransaction()) { command.Transaction = transaction; try { //这里操做数据库 transaction.Commit(); //提交事务 } catch (Exception) { transaction.Rollback(); //回滚事务 throw; } } } } } }事务性管理的挑战
虽然编程模型十分简单,不须要服务执行任何事务,可是这个最适合单个客户端调用单个数据库,服务会启动并管理事务,以下所示:
可是,一个面向服务的应用系统,客户端一次于多个服务交互,而且涉及到多个资源,以下图所示
如今问题是,哪个参与的服务负责发起事务并管理资源?若是你们都服务的话,就会以多个事务结束;若是服务里包含过多的业务逻辑将会引发服务、资源之间紧密耦合的问题;再说哪一个服务服负责提交或回滚事务呢;这个服务如何直到其它事务的 状况呢……
一种可行的方法是,经过为事务协调增长代码能够把客户端与服务结合起来,可是这个比较脆弱,业务流程或服务数量变化都会致使这个方法失效。
刚才介绍的事务类型 称为分布式事务。一个分布式事务包含两个或多个独立的服务(一般在不一样的执行上下文里),或者一个服务包含多个事务资源。对于一个分布式事务,须要依赖两阶段提交协议和一个事务管理器。事务管理器是管理事务的第三方,由它来负责客户端和服务端两阶段提交协议。
为了克服分布式事务的复杂性,事务管理器使用一个称做两阶段提交协议的事务管理协议来决定事务提交或回滚。两阶段提交协议在分布式事务中强调原子性与一致性。让WCF支持多客户端、服务以及资源的分布式事务。当事务工做时,事务管理器会进行监督。当有新的服务加入事务,以及访问到的资源都会与这个事务关联。服务执行业务逻辑资源,资源记录事务内所作的修改。在事务期间,全部的服务(参与到事务里的客户端)必须经过投票决定它们是否提交事务或终止事务。
当事务结束时,事务管理器会检查参与事务投票的全部服务。若是任何一个服务或客户端投票终止事务,事务就不会提交:全部在事务期间对资源的修改都会被抛弃。若是全部的参与者都投票提交事务,那么就会启动两阶段提交协议:
第一阶段,事务管理器询问参与到事务里的全部资源是否对于提交事务期间的修改还有什么意见。注意,事务管理器不会命令资源提交修改,而只是询问它们的意见。第一阶段结束时,事务管理器会综合全部的资源投票结果。
第二阶段,根据投票结果来执行。若是全部的资源都投票提交事务,那么事务管理器会告诉全部的资源提交修改。可是,若是任何一个资源没有提交修改,那么资源管理器会告诉其他的资源回滚修改,而后终止事务,并把系统恢复到事务以前的状态。
资源管理器(RM)是由某个事务管理器管理的、支持原子操做和两阶段提交协议的资源。这个资源必须能够检测本身是否被包含进了事务,并且是否有且只有一次的自动那个加入事务列表。RM能够处理持久化和非持久化资源,好比,事务性整数、字符串和集合。虽然RM必须支持两阶段提交协议,可是,他能够选择使用优化协议。这个协议称为一阶段提交协议,事务管理器(TM)会一次性通知事务管理器执行的结果。
资源管理器在整个事务模型中主要承担以下几种职能:
- 帮助应用实现对目标资源的操做;
- 注册到相应的事务管理器,以便事务回滚得时候能够从事务管理器中接收到恢复请求,实现对数据的恢复;
- 向相应的事务管理器报告本地事务的结果;