结算场景下的跳坑记
前言
本文要说明的是结算服务调用时的错误设计,关于结算系统的细节,没有相关经验,不做描述。此处将结算系统看做一个服务接收方。
结算服务描述:
接收参数包括:结算单号、请求UUID、业务参数、扩展参数。
支持首次下发、失败二次拉起。(区别在于:应对银行系统的失败情况,不必再走结算审核流程)
结算系统根据结算单号,或者请求UUID做幂等性处理。
UUID说明:这个跟单号的区别在于,是标记结算单一次操作的唯一码,可以是系统编码+业务编码+结算单号+状态,那么在结算单的每个状态下的操作都对应一个操作码
调用方:
结算单号生成,请求UUID生成,参数封装。
失败情况二次发起。
错误的调用设计:
结算单号,在下发结算时生成。
故障过程:
当结算发起方在调用结算服务时,生成固定格式的唯一单号,这里采用"业务主键-伪随机数"作为结算单号。系统稳定时,一切正常。但是出现异常时,将存在相同数据,不同结算单号的多条记录情况。
比如:在结算服务超时情况下的调用,此时有两种可能:一种是结算超时,结算系统失败。另一种,结算超时,但是结算单在结算系统正常保存了。此时,调用系统发现超时异常,回滚单据状态至待发起结算。用户又操作点击发起,就会导致两条相同金额不同结算单号记录。
故障改进:
在业务主数据生成时预生成结算单。发起结算时,始终使用预生成的单号,当该结算单生命周期结束时,预生成一条新的结算单号。这样即可利用结算服务的幂等设计防止重复数据的发生。
故障后的思考:
研发人员的程序编码阶段对异常情况考虑的覆盖不全。
测试阶段未覆盖多次发起的场景。假定服务、网络是稳定的。
后续发展:
业务要求在上游审批环节结束后,自动发起结算。考虑失败情况,需要增加重试机制,有了前边的故障改进,才使这种错误免于大面积发生,倘若结算单号不是预先生成,若干次的重试,将会是可怕的后果。
单据在状态流转过程中,还需要考虑状态迁移的限制特性,借鉴状态机理论,增加前置状态校验。目标状态迁移的幂等设计。
版权声明: 本文为 InfoQ 作者【墨凡】的原创文章。
原文链接:【http://xie.infoq.cn/article/d8c79e5c9c6268552433d17c1】。文章转载请联系作者。
评论