系统经过分片改造后,原来的单一数据库将演变成多数据库。如何保证多个数据源同时操作的原子性和一致性是无法回避的问题。一个没有考虑的问题。一般来说,目前分布式系统中事务处理的方式主要有三种:分布式事务、基于BestEfforts1PC模式的事务和事务补偿机制。下面我们将对这三种处理方式一一进行分析。分布式事务这是最著名的多数据源事务处理机制。本文无意对分布式事务做过多的介绍。读者可以参考这篇文章:分布式事务研究,两阶段提交,一阶段提交,BestEfforts1PC模式和事务补偿机制。这里我只想分析一下分布式事务的优缺点。优点:1、基于两阶段提交,最大程度保证了跨库操作的“原子性”,是分布式系统中最严格的事务实现方式。2、实现简单,工作量小。由于大部分应用服务器和一些独立的分布式事务协调器都做了很多封装工作,所以在项目中引入分布式事务的难度和工作量基本可以忽略不计。缺点:系统“水平”缩放的死敌。基于两阶段提交的分布式事务在提交事务时需要在多个节点之间进行协调,最大限度地延迟了提交事务的时间点,客观上延长了事务的执行时间,会导致事务访问共享资源时发生冲突和死锁的可能性会增加。随着数据库节点的增多,这种趋势会越来越严重,从而成为系统在数据库层面横向扩展的“枷锁”。这是许多Sharding系统不采用分布式事务的主要原因。基于BestEfforts1PC模式的事务不同于分布式事务采用的两阶段提交。BestEfforts1PC模式采用单阶段提交,牺牲了事务在某些特殊情况下(崩溃、网络中断等)的安全性,但取得了良好的性能,尤其是消除了水平扩展的束缚。Spring中的分布式事务,使用和不使用XA提供了BestEfforts1PC模型的详细描述。本文提供的Demo代码直接给出了一个在Spring环境下实现单阶段提交的多数据源事务管理的例子。不过需要注意的是,原来的例子是基于spring3.0之前的版本。如果使用spring3.0+,会报如下错误:java.lang.IllegalStateException:Cannotactivatetransactionsynchronization–alreadyactive。如果使用spring3.0+,需要参考spring-data-neo4j的实现。鉴于BestEfforts1PC模型的性能优势和相对简单的实现,被大多数分片框架和项目所采用。事务补偿机制对于那些对性能要求高但对一致性要求不高的系统往往不需要系统的实时一致性,只要在允许的时间段内达到最终一致性即可,这使得事务成为一种补偿机制成为一个可行的选择。事务补偿机制最初是在处理“长事务”时提出的,但对于分布式系统中保证一致性也是一个很好的借鉴。一般来说,交易补偿不同于交易在执行过程中出现错误后立即回滚的方式,交易补偿是一种事后检查和修复的措施。它只期望在允许的时间段内得到最终一致的结果。交易补偿的实现与系统业务密切相关,没有标准的处理方式。一些常见的实现方式有:数据的对账校验;基于日志的比较;定时与标准数据源同步等总结分布式事务,最严格的事务实现,但是性能是个大问题;BestEfforts1PC模式,性能与事务可靠性的平衡,支持系统水平扩展,是大多数情况下最合适的选择;事务补偿机制,只能应用于事务性要求不高,只让数据“最终一致”的系统,牺牲实时一致性来获得最佳的性能回报。
