其他
浅析分布式系统中的补偿机制设计问题
文章目录
一、关于业务补偿机制 1、什么是业务补偿 2、业务补偿设计的实现方式 二、关于回滚 1、显示回滚 2、回滚的实现方式 三、关于重试 1、重试的使用场景 2、重试策略 3、重试时的注意事项 四、业务补偿机制的注意事项 1、ACID 还是 BASE 2、业务补偿设计的注意事项
一、关于业务补偿机制
1、什么是业务补偿
2、业务补偿设计的实现方式
业务补偿设计的实现方式主要可分为两种:
回滚(事务补偿),逆向操作,回滚业务流程,意味着放弃,当前操作必然会失败; 重试,正向操作,努力地把一个业务流程执行完成,代表着还有成功的机会。
一般来说,业务的事务补偿都是需要一个工作流引擎的。这个工作流引擎把各式各样的服务给串联在一起,并在工作流上做相应的业务补偿,整个过程设计成为最终一致性的。
Ps:因为「补偿」已经是一个额外流程了,既然能够走这个额外流程,说明时效性并不是第一考虑的因素。所以做补偿的核心要点是:宁可慢,不可错。
二、关于回滚
1、显示回滚
显式回滚;调用逆向接口,进行上一次操作的反操作,或者取消上一次还没有完成的操作(须锁定资源); 隐式回滚:隐式回滚意味着这个回滚动作你不需要进行额外处理,往往是由下游提供了失败处理机制的。
首先要确定失败的步骤和状态,从而确定需要回滚的范围。一个业务的流程,往往在设计之初就制定好了,所以确定回滚的范围比较容易。但这里唯一需要注意的一点就是:如果在一个业务处理中涉及到的服务并不是都提供了「回滚接口」,那么在编排服务时应该把提供「回滚接口」的服务放在前面,这样当后面的工作服务错误时还有机会「回滚」。 其次要能提供「回滚」操作使用到的业务数据。「回滚」时提供的数据越多,越有益于程序的健壮性。因为程序可以在收到「回滚」操作的时候可以做业务的检查,比如检查账户是否相等,金额是否一致等等。
2、回滚的实现方式
三、关于重试
1、重试的使用场景
2、重试策略
return (retryCount - 1) * incrementInterval;
return 2 ^ retryCount;
return random(0 , 2 ^ retryCount);
int baseNum = 2 ^ retryCount;
return baseNum + random(0 , baseNum);
3、重试时的注意事项
首先对于需要重试的接口,是需要做成幂等性的,即不能因为服务的多次调用而导致业务数据的累计增加或减少。
满足「幂等性」其实就是需要想办法识别重复的请求,并且将其过滤掉。思路就是:
给每个请求定义一个唯一标识。 在进行「重试」的时候判断这个请求是否已经被执行或者正在被执行,如果是则抛弃该请求。
Ps:此外重试特别适合在高负载情况下被降级,当然也应当受到限流和熔断机制的影响。当重试的“矛”与限流和熔断的“盾”搭配使用,效果才是最好。
四、业务补偿机制的注意事项
1、ACID 还是 BASE
2、业务补偿设计的注意事项
因为要把一个业务流程执行完成,需要这个流程中所涉及的服务方支持幂等性。并且在上游有重试机制; 我们需要小心维护和监控整个过程的状态,所以,千万不要把这些状态放到不同的组件中,最好是一个业务流程的控制方来做这个事,也就是一个工作流引擎。所以,这个工作流引擎是需要高可用和稳定的; 补偿的业务逻辑和流程不一定非得是严格反向操作。有时候可以并行,有时候,可能会更简单。总之,设计业务正向流程的时候,也需要设计业务的反向补偿流程; 我们要清楚地知道,业务补偿的业务逻辑是强业务相关的,很难做成通用的; 下层的业务方最好提供短期的资源预留机制。就像电商中的把货品的库存预先占住等待用户在 15 分钟内支付。如果没有收到用户的支付,则释放库存。然后回滚到之前的下单操作,等待用户重新下单。
·END·
相关阅读:
参考文章:lizhengi.blog.csdn.net/article/details/129369229
版权申明:内容来源网络,仅供学习研究,版权归原创者所有。如有侵权烦请告知,我们会立即删除并表示歉意。谢谢!
专注架构技术研究,一起跨越职业瓶颈!
如果您觉得还不错,欢迎关注和转发~