Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
分布式事务第9篇:分布式事务解决方案之最大努力通知型
相关专辑:
分布式事务专题
<div style="display:none"></div> ## 目录 [TOC] ## 1. 支付宝充值案例 假如我们自己有一个电商系统,支持用户使用支付宝充值,流程如下: ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/168/49947125-98d2-4596-b659-10674eff75f4.png) ## 2. 用户支付流程(是一个同步的过程) 1. 用户在浏览器发起充值请求->电商服务 2. 电商服务生成充值订单,状态为0:待支付(0:待支付、100:支付成功、200:支付失败) 3. 电商服务携带订单信息请求支付宝,生成支付宝订单,组装支付宝支付请求地址(订单信息、支付成功之后展示给用户的页面return_url、支付异步通知地址notify_url),将组装的信息返回给用户 4. 用户浏览器跳转至支付宝支付页面,确认支付 5. 支付宝携带支付结果同步回调return_url,return_url将支付结果展示给用户 ## 3. 支付宝将支付结果异步通知给商户 用户支付流程完毕之后,此时支付宝中支付订单已经支付完毕,但电商中的充值订单状态还是0(待支付),此时支付宝会通过异步的方式将支付结果通知给notify_url,通知的过程中可能由于网络问题,导致支付宝通知失败,此时支付宝会通过多次衰减式的重试,尽最大努力将结果通知给商户,这个过程就是最大努力通知型。 商户接收到支付宝通知之后,通过幂等性的方式对本地订单进行处理,然后告知支付宝,处理成功,之后支付宝将不再通知。 ## 4. 什么是衰减式的通知? 比如支付宝最大会尝试通知100次,每次通知时间间隔会递增。比如第1次失败之后,隔10s进行第2次通知,第2次失败之后,隔30s进行第三次通知,间隔时间依次递增的方式进行通知。 ## 5. 如果支付宝一直通知不成功怎么办? 商户可以主动去调用支付宝的查询接口,查询订单的支付状态。 ## 6. 为什么需要进行异步通知? 用户支付过程中,不是有个return_url么?支付宝支付成功之后会携带支付结果同步调用这个地址,那么商户直接在这个return_url中去处理一下本地订单状态不就可以了么?这种做法可以,但是有可能用户的网络不好,调用return_url失败了,此时还得依靠异步通知notify_url的方式将支付结果告知商户。 ## 7. 最大努力通知型用在什么场景? 分布式事务中,不能立即知道调用结果的,被调方业务处理耗时可能比较长,被调方业务处理完毕之后,可以采用最大努力通知的方式将结果通知给调用方。 ## 8. 最大努力通知型要有补偿机制 被调方会尽最大努力将结果通知给调用方,极端情况下有失败的可能,此时被调方需提供查询接口。 调用方对于长时间不知道结果的业务,可以主动去被调方查询,然后进行处理。 ## 9. 不需要通知,主动去查可以么? 可以,被调方会提供查询接口,调用方主动去查询的方式完全是可以知道结果的,不过采用通知的方式实时性更高的一些。 被调方成功之后,会立即通知调用方,但是调用方主动采用查询的方式,那么什么时候查询呢?这个度不好把握,所以两则结合更好。 ## 10. 分布式事务对比分析 在学习各种分布式事务的解决方案后,我们了解到各种方案的优缺点: **2PC**最大的诟病是一个阻塞协议。RM在执行分支事务后需要等待TM的决定,此时服务会阻塞并锁定资源。由于其阻塞机制和最差时间复杂度高, 因此,这种设计不能适应随着事务涉及的服务数量增加而扩展的需要,很难用于并发较高以及子事务生命周期较长 (long-running transactions) 的分布式服务中。 如果拿**TCC**事务的处理流程与2PC两阶段提交做比较,2PC通常都是在跨库的DB层面,而TCC则在应用层面的处理,需要通过业务逻辑来实现。这种分布式事务的实现方式的优势在于,可以让**应用自己定义数据操作的粒度,使得降低锁冲突、提高吞吐量成为可能**。而不足之处则在于对应用的侵入性非常强,业务逻辑的每个分支都需要实现try、confirm、cancel三个操作。此外,其实现难度也比较大,需要按照网络状态、系统故障等不同的失败原因实现不同的回滚策略。典型的使用场景:满,登录送优惠券等。 **可靠消息最终一致性**事务适合执行周期长且实时性要求不高的场景。引入消息机制后,同步的事务操作变为基于消息执行的异步操作, 避免了分布式事务中的同步阻塞操作的影响,并实现了两个服务的解耦。典型的使用场景:注册送积分,登录送优惠券等。 **最大努力通知**是分布式事务中要求最低的一种,适用于一些最终一致性时间敏感度低的业务;允许发起通知方处理业务失败,在接收通知方收到通知后积极进行失败处理,无论发起通知方如何处理结果都会不影响到接收通知方的后续处理;发起通知方需提供查询执行情况接口,用于接收通知方校对结果。典型的使用场景:银行通知、支付结果通知等。 | | 2PC | TCC | 可靠消息 | 最大努力通知 | | ---------- | -------- | -------- | -------- | ------------ | | 一致性 | 强一致性 | 最终一致 | 最终一致 | 最终一致 | | 吞吐量 | 低 | 中 | 高 | 高 | | 实现复杂度 | 易 | 难 | 中 | 易 | ## 11. 总结 在条件允许的情况下,我们尽可能选择本地事务单数据源,因为它减少了网络交互带来的性能损耗,且避免了数据弱一致性带来的种种问题。若某系统频繁且不合理的使用分布式事务,应首先从整体设计角度观察服务的拆分是否合理,是否高内聚低耦合?是否粒度太小?分布式事务一直是业界难题,因为网络的不确定性,而且我们习惯于拿分布式事务与单机事务ACID做对比。 无论是数据库层的XA、还是应用层TCC、可靠消息、最大努力通知等方案,都没有完美解决分布式事务问题,它们不过是各自在性能、一致性、可用性等方面做取舍,寻求某些场景偏好下的权衡。 <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
相关专辑:
分布式事务专题