背景介绍
首先介绍一下实体电商通用的售后流程。
- 用户申请:在用户申请操作时需要填写退货、换货,以及原因。
- 商家审核:商家会根据沟通情况审核售后申请。
- 用户回寄:审核通过后需要用户回寄商品。
- 确认退换:商家收货确认后会给用户退款或者邮寄新货。
虚拟商品的售后通用流程如下:
- 管理员发起退换操作
- 处理退换
- 退:先退货后退款
- 换:先退货后发货
在以上两个流程的处理流程有个共通的地方,就是一次操作需要涉及多个子流程的处理,这就是接下来需要讲的通用售后流程抽象。多个子流程的处理意味着要和多个子系统分别进行沟通处理退货、换货和退款。
这里就涉及到分布式系统的一致性问题了,售后模块作为资源的协调方,我们是否可以采用 TCC 的强一致性方案?答案是 No,成本有点高。普遍的做法是采用弱一致性方案保证最终一致性,我们可以考虑采用 Pipeline 机制。
概念比较
Pipeline 管道模式
在 Pipeline 机制中有三个基本概念:
- Pipeline 管道
- Valve 阀门
- Context 上下文数据
一个 Pipeline 管理多个 Valve,多个 Valve 共享一个 Context 数据。用类图来表达如下:
为了管理处理的进度,我们每个 Valve 都是有状态的,那么所有的状态和就是整个 Pipeline 的状态。
TCC 方案
TCC 是一种补偿事务方案,他要求对每个服务提供如下三个接口:
- Try:尝试对业务进行一致性检查(一致性),然后对资源的锁定(隔离性)。
- Confirm:如果所有的服务都锁定成功并且可执行,就进行确认资源的处理。
- Cancel:如果有问题就释放资源。
它的适用场景有以下两个要求:
- 一致性和隔离性要求比较强
- 执行时间比较短的业务
举例说明是账户间转账、跨系统转账等资金类操作上。
但是它有一个比较明显的缺点就是实现成本比较高,需要协调的服务方越多,系统压力也就越大。
在售后场景中,TCC 是明显不适合的。对于整个售后流程说,各个环节也会出现资源占用导致处理失败的情况,受到 Try 的启发,我们不锁资源,只是在整个处理前挨个进行 qualification 资格检查,全部通过后再进入执行阶段。
责任链模式
责任链模式,用来处理相关业务逻辑的一条执行链,执行链上有多个节点,每个节点都可以处理请求,如果某个节点处理完毕就可以根据实际业务需求传递给下一个节点继续处理或者返回处理完毕的结果。
对于责任链模式,为什么有的实现和 Pipeline 很像。有人对责任链模式进行了如下两种分类:
- 纯责任链:链上只有一个节点会处理请求。比如双亲委派。
- 不纯责任链:链上的每个节点都可以处理请求,并转发到下一个节点。比如 Spring Filter 机制。
从上面来看不纯责任链就是 Pipeline 模式,要说区别目前有如下结论。不纯责任链更偏重于数据的过滤和加工,Pipeline 模式是数据的加工,并且更突出节点的状态。
总结
对于售后事件的各个环节处理,如果其中一个环节执行失败,之前的环节怎么办,有以下几种方式来解决:
- 增加审核环节,对整个事件审核并预判后续环节的可行性。
- 状态回滚,某个环节执行失败,之前的环节都回滚。
- 执行前对各个环节进行资格检查。
- 最严格的 TCC 资源锁定,一起提交一起失败。
以上四种方式各有利弊,需要根据实际场景来判定使用。