- 1、本文档共4页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
从储值卡(会员卡)充值业务看分布式事务的设计
公司有一项储值卡充值业务:客户在微信公众号开通储值卡服务,
通过微信支付往卡里面充值,充值成功后客户可收到消息通知,并进
行消费。
看起来是一项很简单的业务,最初我们储值卡团队的实现也确实
很简单。我们看看最初的实现:
相信聪明的你一眼就能看出问题:
1.压根没有考虑分布式事务一致性,比如第12步根本没有考虑卡
系统充值失败的情况该如何处理,而是默认其一定能成功;
2.大部分的处理都是放在前端业务系统(除了这里的公众号系统,
还有POS机系统,而POS机是通过调公众号系统接口来实现的);
3.第4步直接下单,第5步直接调微信支付,压根没有跟卡系统
有任何通信:这里默认用户的充值行为一定是合法的;
4.在微信的支付回调中(第10步往后),是先处理一系列业务逻
辑,最后才调充值接口,这里也是默认卡充值一定能成功;
看到这里你可能会大呼开发人员是不是没长脑子?
实际情况是,这个版本的开发是几年前的事情了,那时候公司还
是创业早期,第一目标是尽快上线能用,而且客户量没有那么大,虽
然中间也出现过一些数据不一致的情况,也都通过人工处理了事了。
随着公司业务的发展,用户量越来越大,而且还要和第三方合作
(储值卡作为一种支付方式提供给第三方使用),问题出现得也越来
越频繁,不得不将这块提上重构议程。
那么,针对上面提的几点问题,我们大体能想到如下重构项:
1.将充值业务逻辑从前端系统剥离,做成单独的服务;
2.在下单前,先调一下卡系统接口,检查用户的充值行为是否合
法,避免后面不必要的麻烦;
3.在支付回调中,处理充值失败的场景;
初步设计如下:
这里我们重点讨论下对第14步(卡充值接口返回结果)的处理:
1.如果返回充值成功,那万事大吉,该干嘛干嘛;
2.如果失败呢?可能的处理方式如下:
1.继续重试,最多重试3次,如果成功了,万事大吉;
2.如果上面重试还是失败,那么调微信退款,并将订单状态
改成充值失败;
骚年你等等!
你说什么?重试失败了就去退款?
实践中,远程调用失败的一个很大原因是网络超时(而超时的很
大原因又是对方负载过高),而面对超时,我们是不知道对方到底有
没有处理成功的,万一这边把钱退掉了,那边又充值成功咋办?(我
们是SaaS服务商,这时真正的损失方是我们的商户,而商户无疑会找
我们索赔的)
一种方案是:
在多次重试失败后发起微信退款之前,先调卡系统查询接口,如
果查询结果是充值成功,则不退款,继续后续流程,否则发起退款;
该方案在实际中也基本行不通,因为如果那段时间网络有问题或
者对方服务器负载高,查询也有很大概率失败,或者就算查成功了并
返回充值记录不存在,也有可能之前调的充值接口还在跑(比如处于
锁等待状态)。
有人可能会说,没关系啊,就算退款后充值成功了,那后面通过
人工或者系统发现数据问题再处理掉不就行了吗?
问题在于,如果在发现问题之前,用户已经从卡上消费掉了呢
(比如用户当场冲1000然后立马消费掉,这在我们实际场景中是经常
发生的,因为很多商户会搞充值活动,比如冲1000送200)?把卡余
额扣成负数?(这不是我杜撰的,在我们老储值卡系统就出现过几次
这种情况,当时是直接由公司给商户赔钱)
因此,关键在于,当充值中心不知道卡系统有无充值成功的情况
下,需要内部假定充值成功了。
最终,我们决定用定时任务来解决。在微信支付回调中,如果多
次调卡充值接口失败,我们不发起退款,也不进行后续流程,而是在
数据库中写入一条异常记录,然后结束本次处理。
在定时任务中(比如10分钟一次),我们取出那些异常记录,调
卡系统相关接口核对最终状态,如果充值成功了,则补充执行充值成
功的后续流程,否则发起微信退款,并执行其他充值失败流程(如改
订单状态,给用户发通知、回调业务系统等)。
为了防止钱退了后卡又充值成功,定时任务中只处理1小时前的
数据。
另一个隐藏的问题是,在前面的充值流程中,直到微信支付回调,
卡系统都没有关于这次充值行为的任何记录。这可能会导致后续一系
列问题,其中一个
文档评论(0)