
支付系统如何在不确定世界里把账算到分毫不差看Awesome Architecture的状态机、幂等与对账【免费下载链接】awesome-architecture Architecture-first system design: 26 bilingual tutorials, 25 architecture templates, and 6 end-to-end cases covering distributed systems, AI-native systems, RAG, coding Agents, and production trade-offs.项目地址: https://gitcode.com/gh_mirrors/awesomearc/awesome-architecture为什么一笔支付请求超时了绝对不能直接当成「失败」网络会重试、银行会超时、回调会被伪造——支付系统架构必须在这些不确定中做到不重、不漏、不错、笔笔可查。本文带你读懂 Awesome Architecture 中 支付系统架构模板 的核心设计状态机、幂等、复式记账与对账一套让「钱」永远算得清的架构方法。支付系统的灵魂正确性压倒一切 支付系统 一台「正确性压倒一切」的资金状态机一本永远对得平的账。它和大多数系统的最大不同别的系统追求快它首先追求「对」。宁可慢、宁可拒绝一笔交易也绝不能算错一分钱、绝不能扣两次款。关键事实钱不能凭空产生也不能凭空消失。这条物理般的守恒律决定了支付系统几乎所有的架构取舍。三条「不可逾越的边界」先记住约束为什么重要 资金守恒任何时刻账必须对得平不允许中间态把钱「变没」 外部渠道不可靠且异步银行可能超时「状态未知」是常态而非异常 超时 ≠ 失败请求超时了它可能已成功、也可能失败——这是支付最难的地方状态机设计支付单不能乱跳状态支付编排是支付系统的大脑它把每笔支付变成一个有明确状态、不可乱跳的状态机待支付 ──▶ 处理中 ──┬──▶ 成功 ├──▶ 失败 └──▶ 未知 ⚠️ 一等公民状态最关键的设计判断「未知」必须是一等公民的状态而不能粗暴归为「失败」。银行迟迟不回 / 超时 ✗ 错误做法直接判失败 ──▶ 用户可能已被扣款你却记成失败 → 钱消失 ✓ 正确做法状态置为「未知」启动【查询补偿】 隔一会儿主动问银行「这笔到底成没成」 仍拿不准 ──▶ 留给当天【对账】兜底以银行最终流水为准把「未知」当一等公民承认并主动收敛不确定性比假装它不存在安全得多——这正是 12 · 为失败而设计 讲韧性工程的核心思路。幂等设计网络重试时代防重复扣款的生命线 网络一定会重试服务端就必须幂等。不做幂等同一笔支付被发起两次 →重复扣款灾难。标准解法三件套来自 11 · 数据一致性工程幂等键每个请求带全局唯一 ID如「订单 12345 的支付」key pay_order_12345去重服务端用唯一约束保证「同一个键只处理一次」幂等返回重复请求直接返回首次结果绝不重复执行收到请求(keypay_order_12345) ├─ 已存在 ──▶ 直接返回上次结果不重复扣款 └─ 不存在 ──▶ 同一事务里执行扣款 记下 key一起提交 注意最后一句执行扣款和写入幂等键必须在同一个事务里分两步就留下「钱扣了但 key 没记」的破绽。幂等是一切「会被重试的写操作」的安全带不止支付任何分布式写入都该问「重复执行一次会不会出事」复式记账用数据结构本身保证账永远平❓ 账户余额怎么记「直接改余额字段」还是「复式记账」做法后果UPDATE 余额 余额 - 100直观但并发下易丢更新、无法审计、出错难追溯复式记账每笔记成对借贷分录余额由分录累加得出天然守恒、可审计、不可篡改、能精确还原任意时刻正经支付一定用复式记账。账本永远只追加、绝不更新或删除——余额是「把所有分录加起来」算出来的而不是存一个会被覆盖的数字。这是「用数据结构本身保证正确性」的典范正确性来自结构而不是靠程序员不犯错。对账系统应对「状态未知」的终极兜底 即使有了状态机和查询补偿仍可能有拿不准的笔。对账系统是最后一道防线每天把自己的流水和银行 / 渠道的流水逐笔核对以双方都认的事实为准差异自动 / 人工处理。配套的安全要点回调不可信伪造「支付成功」回调是常见攻击 → 验签 一律以己方主动查询为准卡号不落地敏感卡号令牌化PCI-DSS 合规内部系统只见 token审计日志不可删谁、何时、改了什么全留痕核心强一致周边最终一致扣款、记账强一致发短信、加积分、发货通知走事件驱动——把「不能错的」和「晚一点没关系的」分开新手常踩的 6 个坑支付系统反模式清单❌ 误区✅ 正确做法读余额 - 改余额 - 写回复式记账 不可变分录不做幂等重试导致重复扣款幂等键 唯一约束是底线把外部回调当可信来源验签 以己方查询为准超时直接判失败「未知」状态 查询补偿 对账兜底敏感卡号明文存储 / 打日志令牌化卡号不落地追求性能牺牲正确性正确性绝对优先慢一点都好过算错延伸阅读Awesome Architecture 里的相关资料想深入支付系统架构设计按这条路径学习 templates/payment-system/README.md — 支付系统完整架构模板组件职责、数据流、关键决策与演进路线 tutorial/11-数据一致性工程.md — Saga、Outbox、幂等三件套的系统讲解 tutorial/10-分布式系统的硬道理.md — 部分失败、没有全局时钟、exactly-once 是幻觉 tutorial/12-为失败而设计.md — 超时、降级、韧性工程 tutorial/05-数据与状态.md — 为什么数据与状态才是系统真正的难点 一句话记住支付系统它不是「一个能扣款的接口」而是「一台在不确定世界里仍能把账算得分毫不差的状态机」——所有设计都在回答「怎么做到不重、不漏、不错、且笔笔可查」。【免费下载链接】awesome-architecture Architecture-first system design: 26 bilingual tutorials, 25 architecture templates, and 6 end-to-end cases covering distributed systems, AI-native systems, RAG, coding Agents, and production trade-offs.项目地址: https://gitcode.com/gh_mirrors/awesomearc/awesome-architecture创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考