钱包高并发设计:热点账户、幂等扣减与分库分表实践

钱包高并发设计:热点账户、幂等扣减与分库分表实践

本文是“钱包系统设计”专题第一篇,聚焦支付、转账、收单等高并发资金扣减场景。目标不是讲一个能跑的 Demo,而是讲清楚生产系统里最容易出事故的几件事:如何防超卖、如何防重复扣款、如何抗住热点账户、如何在分库分表后仍然把账做对。


一、为什么钱包扣减比库存扣减更难

很多人第一次做钱包系统,会把它类比成库存系统:有余额就扣,没有就返回失败。

这个理解只对了一半。

库存超卖,通常是履约问题;钱包超扣,直接是资损问题。库存少发一件货,还能补发、退款、人工介入;钱包一旦多扣、漏记、错记,就会变成真实的资金差错、对账差异、投诉升级,甚至审计问题。

所以钱包扣减的第一原则不是快,而是:

  • 不能重复扣;
  • 不能扣成负数;
  • 不能成功返回但账没落;
  • 不能只改余额不记流水;
  • 不能局部成功后没人兜底。

换句话说,钱包系统不是一个“余额字段更新器”,而是一个围绕账户、流水、状态机、幂等与补偿构建的资金账务系统。


二、从一次真实故障切入:为什么会“又慢又错”

某交易平台做大促时,支付链路峰值达到 6 万 TPS。用户付款后,钱包系统要同时完成三类账务动作:

  1. 扣减用户余额;
  2. 增加商户待结算余额;
  3. 增加平台手续费账户余额。

事故现象非常典型:

  • 支付接口 P99 从 80ms 飙到 7s;
  • MySQL 活跃线程暴增,连接池耗尽;
  • 平台手续费账户更新严重排队;
  • 回调重试导致少量交易重复扣减;
  • 流水表写入延迟,账实不一致告警出现。

复盘后,根因不是一个点,而是一整串设计问题叠加:

  • 用户余额、商户入账、平台手续费全部放在同一个同步事务中;
  • 同一平台账户被高频更新,形成单行热点;
  • 幂等只做了 Redis SETNX,数据库没有唯一约束;
  • 流水表单表过亿后,索引写放大严重;
  • 所有资金路径都要求实时入账,没有区分“必须强一致”和“允许异步汇总”。

这类事故说明,钱包高并发设计不是“给数据库加锁”那么简单,而是要先分清楚三种不同性质的资金动作:

  • 用户侧扣减:必须强一致;
  • 热点收款账户入账:可以削峰异步;
  • 账务审计流水:必须完整、可追溯、可重放。

三、先定义清楚业务模型

在讲架构之前,先把领域模型定义准。钱包系统里至少有四个关键对象。

3.1 账户 Account

账户是资金承载实体,核心字段通常包括:

  • account_id:账户 ID;
  • owner_id:用户 ID 或商户 ID;
  • account_type:USER、MERCHANT、PLATFORM;
  • available_balance:可用余额;
  • frozen_balance:冻结余额;
  • status:NORMAL、LOCKED、CLOSED;
  • version:乐观锁版本。

3.2 资金流水 AccountFlow

流水是账务审计依据,必须满足“可查、可重放、不可篡改”。一笔业务通常至少会生成一条或多条流水,例如:

  • 用户支付扣减流水;
  • 商户收款流水;
  • 平台手续费流水;
  • 补偿冲正流水。

3.3 账务指令 LedgerCommand

业务系统不应该直接“改余额”,而应该提交账务指令,例如:

  • PAY_DEDUCT
  • TRANSFER_OUT
  • TRANSFER_IN
  • FREEZE
  • UNFREEZE
  • FEE_COLLECT

把“业务意图”和“账户更新”解耦,后续才有幂等、审计、补偿、对账的空间。

3.4 业务单号 BizOrder

任何资金动作都必须能回溯到原始业务单号,例如:

  • 支付单 pay_order_no
  • 提现单 withdraw_order_no
  • 转账单 transfer_order_no

后续所有幂等设计、去重设计、对账设计,都是围绕业务单号展开的。


四、钱包高并发的四个核心矛盾

4.1 既要高并发,又要不超扣

高并发意味着大量请求同时命中同一个服务实例、同一个数据库、甚至同一行记录;不超扣意味着必须对余额校验和扣减做原子控制。

4.2 既要防重复,又不能把吞吐做没

支付通知重试、MQ 重投、网关重试、客户端超时补发,都会造成重复请求。单纯加全局锁会很安全,但吞吐会急剧下降。

4.3 既要分库分表,又要维持账务闭环

账户表可以分片,流水表也可以分片,但一笔交易可能涉及多个账户、多个分片、多个服务。分了之后,如何保证账平,是更大的难题。

4.4 既要热点削峰,又要最终账准

平台手续费账户、大商户收款账户天然是热点。直接同步写 DB,一定会卡;全走缓存异步,又会有一致性风险。工程上必须分层处理。


五、总体架构:把“强一致路径”和“削峰路径”拆开

生产级钱包系统,建议采用“双路径架构”:

  • 路径 A:用户余额强一致扣减路径;
  • 路径 B:热点入账异步汇总路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值