掘金 后端 ( ) • 2024-04-09 18:03

theme: scrolls-light

千秋二壮士,烜赫大梁城。

1 前言

在前文中已经讲述了账户设计的逻辑,并且在业务层设计了具体的业务,如红包发送以及积分分发,在本文中将讲解 C 端账户的操作,结合业务的特点编写实现过程,这里借鉴了 AOL 的思想,在操作业务之前先记录日志,并且操作日志和业务处理放在一个事务里处理。

2 账户接口

在前文的账户设计中已经说明了 C 端账户的接口设计,主要是账户的开户以及账户交易,账户交易通常来讲就是账户的出账和入账,至于其它的消费、转入、转出等操作其实都是账户的进和出,只不过操作类型不同,不同的操作类型下面还有不同的业务类型,这两项基本就可以覆盖所有的场景。

账户操作类型 -> 业务类型(一种操作类型对应多种业务类型) 比如操作类型为出账,业务类型可以是消费、转账、红包、打赏等业务。可以理解为业务类型是操作类型的详细说明,操作类型是业务类型的大类总结,因为从操作类型上可以看出来账户的出入,但是业务类型不一定能看出来对账户的影响。

此外账户还需要设计状态的修改,账户信息的查询、账户的统计等诸多查询统计操作,这些对账户来说也是十分重要的。账户信息分为热数据(账户余额)和冷数据(账户信息),冷和热数据只是相对而言的,一般而言冷数据和热数据是需要放入不同的表,这样可以减少数据更新操作对数据库影响,毕竟数据库表数据量越小其事务操作消耗也小。但是对 C 端账户而言,是需要分库分表的,所以账户表是不需要分开设计的,因为每个表的数据量相对小,但是对于 B 端账户而言,其存在热点账户,操作的频度比 C 端更高,所以 B 端账户是需要分开设计。

3 代码实现

不论是 B 端账户,还是 C 端账户,都是需要一个用户在数据库中存在,需要简单创建一个用户表来支持业务的开展。

在操作账户开户时,需要先校验账户是否存在,然后初始化账户数据,这里没有使用注解式事务,所以保存数据操作略显复杂。在大型项目开发时,由于其项目复杂性,注解式事务的使用简便再加上项目开发人员的认知不一致,通常会导致事务使用的泛滥。所以使用编程式事务可以解决这一问题。在后续代码中也会经常出现这一非常规操作。 1694877246519.png

Tips: 这里的账户表涉及到分库分表,通常情况下分库分表键是 userId, 这样可以保证同一个用户的所有账户在同一张数据库表中,方便账户数据的查询。由于账户业务的单一性,账户的查询不会关联其它数据库表。

至于账户的交易操作,主要分为两种情况,一种是出账一种是入账,在操作数据之前需要先校验账户数据,然后初始化账户流水,在事务中需要使用读锁来锁住账户信息,通过计算账户的操作金额,记录账户操作余额,记录到账户流水表中。 1694878071858.png

计算账户金额的操作,入账时计算比较简单,主要是出账时需要判断用户是否可以欠款,需要记录欠款时,记录欠款字段,否则提示操作失败。 1694878105390.png

由此,账户的核心接口已经实现完毕。

4 总结

在本文中,主要讲解了 C 端账户的设计以及实现过程,主要是账户的交易接口,C 端的交易比较简单,在后续文章中将介绍 B 端账户操作,其中涉及的业务比较复杂,欢迎大家关注。本文中所涉及的代码已经上传至 github, 欢迎交流学习。项目地址 springboot-auth