当支付平台收到扣款结果的处理伪代码,我们可以看到如果是多个服务,位于不同主机,不同的网络当中,我们没有办法用本地事务保证要么一起成功要么一起失败
/**
*支付平台收到第三方支付平台的扣款通知
**/
public function completeOrder() {
orderDao::update(); // 订单服务本地更新订单状态
accountService::update(); // 调用资金账户服务给资金帐户加款
pointService::update(); // 调用积分服务给积分帐户增加积分
accountingService::insert(); // 调用会计服务向会计系统写入会计原始凭证
merchantNotifyService::notify(); // 调用商户通知服务向商户发送支付结果通知
}
一个业务流程中要跨多个服务调用,就有可能会遇到分布式事务问题。 订单、支付、入账等核心流程中,数据的准确性和可靠性尤为重要!
上图当中就体现了分布式事务的处理方式,接下来我们大致的了解下这些方式的适用场景及相关理论具体的我们在用代码实现的时候可以回过头来看。
BASE理论及CAP定理
BASE
BA: Basic Availability 基本业务可用性(支持分区失败)
S: Soft state 柔性状态(状态允许有短时间不同步,异步)
E: Eventual consistency 最终一致性(最终数据是一致的,但不是实时一致)
原子性(A)与持久性(D)必须根本保障
为了可用性、性能与降级服务的需要,只有降低一致性( C ) 与 隔离性( I ) 的要求
酸碱平衡(ACID-BASE Balance)
CAP定理
定理: 对于共享数据系统,最多只能同时拥有CAP其中的两个,没法三者兼顾。
任两者的组合都有其适用场景
真实系统应当是ACID与BASE的混合体
不同类型的业务可以也应当区别对待
实现
业务处理服务在业务事务提交前,向实时消息服务请求发送消息,实时消息服务只记录消息数据,而不真正发送。业务处理服务在业务事务提交后,向实时消息服务确认发送。只有在得到确认发送指令后,实时消息服务才真正发送
消息
业务处理服务在业务事务回滚后,向实时消息服务取消发送。消息状态确认系统定期
找到未确认发送或回滚发送的消息,向业务处理服务询问消息状态,业务处理服务根
据消息ID或消息内容确定该消息是否有效
约束
被动方的处理结果不影响主动方的处理结果,被动方的消息处理操作是幂等操作
成本
可靠消息系统建设成本
一次消息发送需要两次请求,业务处理服务需实现消息状态回查接口
优点、适用范围
消息数据独立存储、独立伸缩,降低业务系统与消息系统间的耦合
需要实现的服务
可查询操作、幂等操作
方案特点
兼容所有实现AMQP标准的MQ中间件
确保业务数据可靠的前提下,实现业务数据的最终一致(理想状态下基本是准实时一致)
适用
1、对应支付系统会计异步记账业务
2、普通的积分账户增加积分的服务
实现
一个完整的业务活动由一个主业务服务与若干从业务服务组成
主业务服务负责发起并完成整个业务活动
从业务服务提供TCC型业务操作
业务活动管理器控制业务活动的一致性,它登记业务活动中的操作, 并在
业务活动提交时确认所有的TCC型操作的confirm操作,在业务活动取消
时调用所有TCC型操作的cancel操作
成本
实现TCC操作的成本
业务活动结束时confirm或cancel操作的执行成本
业务活动日志成本
适用范围
强隔离性、严格一致性要求的业务活动
适用于执行时间较短的业务(比如处理账户、收费等业务)
用到的服务模式
TCC操作、幂等操作、可补偿操作、可查询操作
方案特点
不与具体的服务框架耦合(在RPC架构中通用)
位于业务服务层,而非资源层
可以灵活选择业务资源的锁定粒度
实现
业务活动的主动方,在完成业务处理之后,向业务活动的被动方发送消息,
允许消息丢失。
业务活动的被动方根据定时策略,向业务活动主动方查询,恢复丢失的业
务消息。
约束
被动方的处理结果不影响主动方的处理结果
成本
业务查询与校对系统的建设成本
适用范围
对业务最终一致性的时间敏感度低
跨企业的业务活动
柔性事务解决方案:最大努力通知(定期校对)
方案特点
业务活动的主动方在完成业务处理后,向业务活动被动方发送通知消息(允许消息丢失)
主动方可以设置时间阶梯型通知规则,在通知失败后按规则重复通知,直到通知N次后不主动方提供校对查询接口给被动方按需校对查询,用于恢复丢失的业务消息
应用案例
银行通知、商户通知等(各大交易业务平台间的商户通知:多次通知、查询校对、对账文件)