题目重点:商户受理结果、外部批准和批量提交是不同阶段。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练hold向外部network请求authorization,approved后保留授权金额;charge是独立请求,成功记录capture意图,再按network生成定时batch。实际network支持的撤销/过期/部分capture另定。
- 金额用最小货币整数单位,currency必存;不将“Kafka写入成功”返回为hold approved。示例架构讨论协议,不提供支付合规或具体provider现行政策。
解题路线
- Hold(id,merchant,idempotency_key,amount,currency,network,status,network_ref)与Charge(id,hold_id,amount,status,batch_id)分别建状态机。hold pending→approved/declined/unknown;charge只在可用授权范围内原子预留,避免两次并发capture超额。
- 同步hold等待network确定结果,有时限后返回pending+status URL;callback/query最终确认unknown。幂等键唯一约束并绑定请求digest,同key不同amount拒绝,同key重试返回同逻辑交易状态。
- 调用network前写持久操作/outbox,带稳定network request ID;发送成功回包丢失不能当declined或直接创建新hold。network不支持幂等时通过查结果/对账解决unknown,不能靠本地事务保证外部调用一次。
- charge落库后用状态索引或CDC增量按network/business_date分桶,全天准备immutable分片,截止时形成manifest(sequence,count,total_amount,digest)。batch状态prepared→sent→acknowledged→reconciled;文件传输重试保持batch ID/版本并记录每笔受理结果。
- 每天22点需明确时区、business date、截止快照及迟到/小费更新规则。封账后新变更走adjustment或下一batch,不原地修改已发送文件。批次失败可按network隔离,merchant看到charge accepted与settled是不同返回状态。
手动走一遍
hold100 approved,charge60成功后剩可用40;两个并发charge30不能都通过,否则总capture120。10,000TPS若全天持续约8.64亿请求/day;全量晚间扫描和单文件生成很危险,增量分桶/分片让截止只做manifest与最终校验。batch上传成功但ACK丢失:查稳定batch ID状态,再安全重试;不能创建新batch再次扣款。
规模与取舍
基础交易写按merchant/transaction分片,状态转移需要局部原子检查;batch总体O(入批交易数),按network及固定partition并行。吞吐TPS不等于唯一交易数,重试/hold/charge分别计容量;账目金额总和需可核对。
易错点与追问
容易失分的边界
- 把hold与charge混成一个成功状态丢失独立触发条件。
- 受理进入Kafka就告诉merchant批准,实际network可能拒绝。
- 以状态全表LSI作为所有规模万能解,不核对数据库分区/索引约束。
继续深挖
- 授权过期、部分charge、refund和小费调整如何形成独立账目而非覆盖金额?
- batch部分受理时,交易级状态与批次级状态怎样避免错误一起成功?
