关于 Tigshop 资金/积分字段设计的优化建议

180
类别: 
需求建议

从一次并发事故说起:为什么我建议把余额从 user 表里拆出去

本文是对 Tigshop 商城系统数据模型设计的一点探讨,起因是我们团队在二次开发中遇到的实际问题。写出来供官方团队和社区开发者参考,无意否定现有设计,纯属技术交流。

一、先说结论

建议将 user、shop、vendor 三张主表中的资金/积分类字段迁移至独立的账户表中。
涉及字段:

字段
userbalance、frozen_balance、commission_balance、frozen_commission_balance、points、growth_points
shopshop_money、frozen_money
vendorvendor_money、frozen_money

这不是说现有设计“错了”,而是随着业务发展,这种设计在高并发场景下会逐渐暴露问题。趁早调整,成本最低。

二、从一个真实场景说起

假设这样一个场景:

用户 A 在 App 上修改昵称,同时该用户正在下单支付。两个操作几乎同时发生。

按照 Tigshop 现有的代码逻辑(MyBatis-Plus updateById),修改昵称时会把 user 表的整行数据查出来再更新回去。如果下单支付先扣了余额,修改昵称的更新又把旧余额覆盖回去了。

扣款被“吞”了。

这不是理论分析,而是我们在压测中真实复现过的问题。

也许有人说:“改昵称的时候把余额字段置空,MyBatis-Plus 就不更新它了。”确实可以规避,但实际开发中,每个开发人员写代码的习惯不同,资金安全不能依赖于“每个人都记得正确传参”。

资金字段应该有独立的、统一的服务入口来管控,而不是躺在主表里被随意更新。

三、现有设计存在哪些问题

3.1 行锁竞争

资金、积分是高频更新字段,昵称、头像也是高频更新字段。它们在同一行上,UPDATE 互斥。

  • 改昵称的请求阻塞了充值的请求
  • 下单扣款的事务锁住了用户信息更新

3.2 字段覆盖丢失

(接第二部分的例子,此处略,前面已有详细描述)

3.3 事务范围过大

下单时需要同时扣余额、加积分、扣库存、更新店铺资金。user 表作为热点表被锁在整个事务中,响应时间越长,锁等待越严重。

3.4 表职责不单一

user 表现在承载了四种不同性质的资产:

  • 余额(普通资产)
  • 佣金(分销资产)
  • 积分(权益资产)
  • 成长值(等级资产)

新增任何一种资产类型(如红包、优惠券额度),只能继续往表里堆字段。长此以往,表结构将越来越臃肿,维护成本越来越高。

3.5 现有流水表已经做得很完善,只差最后一步

这里必须肯定一下:Tigshop 已经设计了 user_balance_log、account、vendor_account_log 三张流水表,字段完整、结构清晰,说明官方在资金安全方面是有意识的。

现在的情况是:流水表已经到位了,但余额还留在主表里。 只差把“当前余额”独立成账户表,整个资金模块就能彻底解耦。

4、最后

这个建议并非是否定 Tigshop 的现有设计——事实上,Tigshop 的流水表设计已经优于很多同类型产品。我们提出这个优化,是希望 Tigshop 在资金安全和高并发方向上走得更远、更稳。

一个好的资金模块,应该有清晰的边界:主表管身份,账户管资产,流水管明细。 三者各司其职,互不干扰,才能支撑起业务长期稳健的发展。

以上是我们团队在二次开发中积累的一点思考,分享出来供 Tigshop 官方和社区开发者参考。如有不准确之处,欢迎指正讨论。

评论1
/ 1000
最热
最新
感谢牧歌同学的深度分析,字段梳理都很扎实,本次也会跟技术部门深度讨论加入后续计划。

先说资金安全部分:Tigshop 的资金变动统一收口在独立 Service 中,每笔变动都在事务内先加行锁、再更新并同步写入流水,扣减本身不会丢,数据不会错乱,这一点可以放心。

提到的锁的问题是客观存在的:资金字段与昵称、头像等高频字段同行,高并发下确实会有行锁竞争、拉长锁等待。这是我们在快速开发、保持结构简单与极致并发性能之间做的取舍,对绝大多数业务场景是够用的,但在高并发场景下确实有优化空间,同时未来也会对高并发场景方向不断优化升级。

另外,我们的微服务产品 VortMall 目前的产品方向就是按这套思路设计的,追求高并发场景的同学可以关注一下。欢迎继续参与讨论。再次感谢!
点赞
评论
1
1
收藏