背景
在云中,应用程序频繁的修改数据,而这些数据可能分布在不同地理位置的各式各样的数据源中。为了避免冲突并提供性能,应用程序不应试图提供强一致性事务,而应实现最终一致性。一个事务当中,可能会由一系列的步骤构成,当所有操作完成时,系统会达到最终的一致性。
最终一致性模型中最显著的一个难题是如何处理无法挽回的失败步骤。一般情况下,由于事务的复杂性,数据不可能简单地按照事务的执行顺序的逆序进行回滚或撤销,另外,如果跨越多个不同的数据结果,也必须在撤销工作中保证操作的可靠性,防止系统最终不一致。
对数据造成影响的一个实现最终一致性的操作并不一定发生在数据库。在面向服务架构(SOA)的环境中,一个操作可能会调用服务中的方法并引起服务状态发生变化。为了撤销此操作,也要撤销改变的状态。
目的
当一个或多个执行步骤执行失败时,通过一系列步骤撤销操作来总体定义一个最终一致性的操作。
建议方案
实现一个补偿事务,用来将系统状态转移到一个可用的状态。原因在于,补偿事务可能无法简单的将系统状态通过撤销操作替换为起始的操作状态,因此,这个处理通常是应用程序定制的,并依据操作的工作性质来决定。
一个通用的补偿模式实现最终一致性操作的途径是使用工作流。随着初始操作的执行,系统会记录每一个步骤的消息及其撤销方式。如果操作失败,则按照之前记录的步骤倒带回去,并执行撤销操作。如果多个步骤可以并行,可以对其撤销步骤进行并行处理。
补偿事务本事也是一个最终一致性操作,同样也会失败。所以,在执行补偿事务时,对失败的步骤进行重试可能会很重要,需要慎重设计。补偿事务中的步骤一般定义为幂等性命令(有关幂等性,参考深入理解幂等性)。
考虑因素
超时机制
:由于无法判断那些操作会失败,并且可能会导致阻塞,所以有必要提供某种形式的超时机制;定制化
:补偿事务理通常是应用程序定制的,并依据操作的工作性质来决定;幂等性命令
:补偿事务中的步骤一般定义为幂等性命令;恢复策略
:补偿事务不一定非要将系统中的数据状态恢复为最初操作时的状态;使用时机
:将能够触发补偿机制的故障最小化,更多的考虑使用重试逻辑。当一个操作失败了,先尝试将其作为一个短暂的异常处理并重复执行该步骤。只有步骤重复失败或一开始就失败,才放弃这个操作,并开始执行一个补偿事务。
适用情况
只针对一些发生异常后必须撤销的操作。