账户设计-用户积分撤回实践
东临碣石,以观沧海。
1 前言
在前文中已经分析并讲解了如何实现用户积分的分发,作为一个完整的业务,在本文中将继续讲解积分撤回的业务。积分的撤回业务是对积分分发的业务补充,积分分发主要是对用户消费、充值、参与活动的奖励,当用户取消参与的活动是时,则需要将之前分发的积分进行撤回。
2 业务分析
积分分发的操作可以是单笔和批量,但是对于积分的撤回只能是单笔同步操作。积分的撤回从业务上说发生的概率低,而且撤回的金额不能大于已经分发的金额。以下是积分撤回的几个条件。
1 积分的撤回需要传入原分发的单号,用于校验原分发金额,根据原单进行撤回。
2 积分的撤回需要校验撤回金额不能超限,具体公式如下所示:
请求撤回金额 >= 原积分分发金额 - 已经撤回的积分
结合之前的用户积分分发的逻辑,设计的积分分发撤回表结构如下图所示:
撤回记录需要关联分发记录,相关的业务参数需要从分发表中获取。
4 业务实现
如下图所示,进入积分撤回业务操作时,需要先判断原分发记录是否存在,并且获取原分发金额,进行第一次预校验,请求撤回金额不能大于原分发金额。之后还需要校验撤回金额的大小,撤回金额不能为负数。
在本次撤回操作执行之前,可能还存在已经撤回成功或者处理中的撤回单,需要查询已经存在的撤回记录,累计求和其撤回金额,本次撤回金额要小于剩余可撤回的的金额,否则会导致业务的数据错乱,导致撤回金额大于分发金额的情况,如果情况发生可能会导致客诉或者资损的情况。
完成了前面的业务逻辑校验后,则需要创建撤回记录,这个操作还是基于 aol 的操作思想,主要是规避分布式事务的问题,以日志或者记录的状态来驱动业务的进行,即满足了业务逻辑要求,也实现了接口的幂等操作。
在记录了撤回日志后,就可以进行 C 端的账户的出账和 B 端账户的入账操作,由于这两个动作分别归属于两个业务系统,所以在操作之前需要分别记录对应的操作日志,操作日志记录完毕后才能调用服务的交易接口执行动作,在业务执行完成后需要修改操作日志表状态。撤回的操作,需要先进行 C 端的扣减,在执行 B 端的入账操作。
在完成底层的账户操作后,如果两者都成功,则可以修改撤回表的数据状态,如果两者有一个没有成功,则不能修改,同时需要定时任务来驱动进行重试,直到业务成功为止。同样的,也可以由上游主动发起重试,在这个过程中,需要上游先进行撤回业务的状态查询,然后根据业务需要在进行后续的操作。
6 总结
在本文中,主要介绍了积分分发的逆向撤回逻辑。撤回的逻辑是单笔同步操作,主要是考虑到业务的闭环,在这个过程中要理解先记录日志在进行操作的思想。这样的操作流程在复杂系统交互中很常见,即可以完成业务接口的幂等性,也可以规避分布式事务。本文中所涉及的代码已经上传至 github
, 欢迎交流学习。项目地址 springboot-auth。
转载自:https://juejin.cn/post/7381855349463662601