手册
一次性有效处理付款 (Effectively Once Processing In Payments)
一次性消息传递是一个谎言。深度防御与幂等、去重、发件箱、对账相结合,如何实现一次见效的业务成果?
分布式支付引擎
部分 20 的 22
一系列分布式支付架构弥合了捕获和完成之间的差距。
在上一节中,我们看到恢复管道首先遵循自动化原则,并且基于证据的操作手册在唯一性墙中发挥作用。本节深入探讨管道基础上的消息传递保证,以及业界最常见的误解:一次性交付。
经纪商卖家承诺“恰好一次语义”。事实上,在分布式系统中,物理上并不能保证消息只会被处理一次。网络出现故障,工作人员崩溃,经纪人重新发送。问题不是“消息到达了多少次”;而是“消息到达了多少次”。 作业结果发生了多少次。```text Exactly-once messaging → imkansız (at-least-once + failure = duplicate) Effectively-once outcome → mümkün (defense in depth)
## 第一次提到的概念```text
📦 At-Least-Once Delivery
Mesaj en az bir kez ulaşır; ağ hatasında tekrar gönderilebilir.
📦 Effectively-Once
Mesaj birden fazla kez işlense bile iş sonucu (charge, refund, order) yalnızca bir kez gerçekleşir.
📦 Defense in Depth
Tek bir mekanizmaya güvenmek yerine, birden fazla bağımsız koruma katmanı.
📦 Idempotent Consumer
Aynı mesajı ikinci kez aldığında aynı sonucu üreten, yan etki yaratmayan tüketici.
```一次性消息传递不是代理功能;这是一种有效第一的系统设计。
## 恰好一次为什么要撒谎
工作人员接收消息,处理它,发送确认 - 但确认在网络中丢失。代理重新发送消息。 Worker 进行第二次处理。这就是至少一次传递的本质;无论经纪人如何声称“恰好一次”,消费者端的重复是不可避免的。```text
Worker mesajı işler → sonuç: Captured
Ack ağda kaybolur
Broker mesajı tekrar gönderir
Worker tekrar işler → sonuç: ??? (çift charge riski)
```问题不在于消息到达的次数;而在于消息到达的次数。这就是第二次降临时所发生的事情。如果第二次访问没有副作用,就说明已经有效实现了——一次。
## 纵深防御:一层是不够的
实际上,业务成果是互补层的组合。仅有这两者还不够;所有这些共同产生结果“至少到达一次的消息最多产生一次效果”。```text
Katman 1: Idempotency key (API)
→ aynı key ile ikinci charge isteği reddedilir
Katman 2: Consumer dedup (messaging)
→ aynı message id ikinci kez işlenmez
Katman 3: DB uniqueness constraint
→ aynı idempotency key ile ikinci satır yazılamaz
Katman 4: Outbox pattern
→ event yalnızca transaction commit ile birlikte yayınlanır
Katman 5: Reconciliation
→ katman 1-4'ün kaçırdığı drift'i periyodik olarak düzeltir
```如果一层发生故障,另一层将接管。如果省略幂等性键,则唯一性约束将被捕获;如果省略约束,则协调修复。
## 每层的问题都不同
|层 |问题 |受保护 |
| --- | --- | --- |
|幂等性密钥 |又是同样的意图吗? | API级别双倍收费|
|消费者重复数据删除 |又是同样的信息吗? |消息层面的双重交易 |
|唯一性约束|第二行有相同的键吗? | DB级双记录|
|发件箱 |该事件是在没有提交的情况下发布的吗? |损失或提前事件|
|和解| Local 和 PSP 不兼容吗? |逃脱的一切|
## 如何编写幂等消费者
幂等消费者规则:相同的输入,相同的输出;第二次调用没有副作用。```text
PaymentCaptured webhook (messageId=wh_991)
→ dedup tablosuna bak: wh_991 işlendi mi?
→ evet → skip (log: duplicate suppressed)
→ hayır → finalize, dedup tablosuna yaz
```最终确定步骤本身必须是幂等的:如果付款已经是 `Captured`,则不应再次发出任何事件,不应再次创建任何订单。 Dedup 表保留了消息层;终端状态控制保护业务逻辑。
## 发件箱:事件和状态在同一个事务中
发件箱模式解决了“状态已更新但事件未发布”或“事件已发布但状态未更新”的困境。事件与本地事务一起写入发件箱表;单独的发布者读取发件箱并将其发送给代理。```text
BEGIN TRANSACTION
UPDATE payment SET status=Captured
INSERT INTO outbox (event=PaymentCaptured, paymentId=8812)
COMMIT
→ publisher outbox'ı okur → broker'a gönderir
→ gönderim başarılı → outbox satırını siler
```Outbox 不提供一次性消息传递,但它确实确保状态和事件之间的一致性。和解抓住了那些从发件箱逃脱的人。
## 经常混淆的区别```text
❌ Broker exactly-once = sistem exactly-once
✓ Broker dedup + consumer idempotency + DB constraint = effectively-once
❌ Idempotency key her yerde yeterli
✓ Idempotency key API'yi korur; webhook ve async worker ayrı katman ister
❌ Effectively-once = perfect system
✓ Effectively-once = iş sonucu bir kez; tutarsızlık penceresi reconciliation ile kapanır
```## 交付保证与业务成果
|保修|它承诺什么?是否足够支付费用? |
| --- | --- | --- |
|至多一次 |消息一旦丢失,就可能丢失 |否 — 付款丢失 |
|至少一次 |消息至少可以重复一次 |不——单独|
|恰好一次(经纪人)|理论上,实际上它在消费者方面崩溃了|没有 |
|一次有效(系统)|作业结果一次 |是的 |
## 一次有效的清单
1. API 收费请求是否受幂等密钥保护?
2. webhook 和异步消费者中是否有消息 ID 重复数据删除?
3.支付表中幂等键是否有唯一性约束?
4. 状态改变和事件广播是否与发件箱模式在同一事务中?
5. Finalize handler是否会在终端状态下跳过而不重新操作?
6. Reconciliation 是否定期扫描第 1-5 层遗漏的漂移?
## 本文中您应该记住的内容
1. 一次性消息传递是一个谎言;至少一次+失败=重复是不可避免的。
2. 有效——通过深度防御,一旦实现业务成果就可能实现——一层是不够的。
3. 每层保护都回答不同的问题;他们必须共同努力。
4、和解是最后一层;它补充而不是取代先前的层。
> 即使您的经纪人承诺一次,您的支付系统也不应该相信它——它应该相信的是有效地深入构建业务成果。
在下一节中,我们将继续综合这个由 22 部分组成的旅程:生产支付引擎设计清单。
FAQ
Frequently asked questions
什么是至少一次交付?
消息至少到达一次;网络错误时可以再次发送。
什么是一次有效?
即使消息被处理多次,作业结果(收费、退款、订单)也仅发生一次。
“经纪商精确一次 = 系统精确一次”是否正确?
Broker 去重 + 消费者幂等性 + DB 约束 = 有效一次
本节修复了什么?
经纪商卖家承诺“恰好一次语义”。事实上,在分布式系统中,物理上并不能保证消息只会被处理一次。网络出现故障,工作人员崩溃,经纪人重新发送。问题不是“消息到达了多少次”;而是“消息到达了多少次”。 **作业结果发生了多少次**。一次性消息传递是一个谎言;至少一次+失败=重复是不可避免的。在上一节中,我们看到恢复管道首先遵循自动化原则,并且基于证据的操作手册在唯一性墙中发挥作用。本节深入探讨管道基础上的消息传递保证,以及业界最常见的误解:一次性交付。
学到的工程原理
- 一次性消息传递是一个谎言;有效——一旦工作结果成为可能。
- 深度防御:幂等性、重复数据删除、唯一性、发件箱、协调协同工作。
- 每层保护都回答不同的问题;一层还不够。
继续阅读
继续阅读
系列中的下一个
设计生产支付引擎
22 部分系列的综合:具有结账协调器和提供商网关的生产支付引擎的架构清单。
系列中的下一个
付款回收管道和操作手册
自动化之前:协调工作人员和恢复管道。当独特性之墙阻碍重播时,基于证据的人类操作手册就会发挥作用。
同系列
金融科技公司真正在寻找什么?
职业视角:金融科技公司而非 Stripe SDK;它寻求失败思维、和解、幂等性和证据驱动的思维。