D5 · 协议、安全与退款后端设计
本日安排:8 小时净学习。休息另计,算法可独立安排。
- 2.5 小时:AG15–AG18、AG22–AG23,协议与安全。
- 1.5 小时:DS04–DS06,一致性与容量。
- 2 小时:案例 A,完整退款服务设计。
- 1 小时:安全追问与 MCP 本地观察。
- 1 小时:闭卷纠错。
多 Agent 的控制流与拆分条件
Section titled “多 Agent 的控制流与拆分条件”把 Agent 拆成“客服 Agent、订单 Agent、退款 Agent”看起来职责清楚,但如果它们只是把同一个任务重复转述,系统会多出上下文搬运、协调、失败恢复与审计成本。先考虑一个 Agent 配合明确的程序化步骤或普通工作流。拆分有收益的条件通常是子任务可独立并行、专业上下文确实需要隔离,或不同执行单元必须有清楚不同的权限;需要把收益与协作延迟、冲突合并和运行成本一起比较。
Agent-as-tool 与 handoff 的控制关系不同。前者是父 Agent 发起子调用并拿回结果,父流程仍继续负责后续决策;handoff 则把接下来处理任务的控制权交给另一个 Agent。无论采用哪种形式,子 Agent 的模型上下文不构成安全边界。权限来自工具服务端对主体、对象和动作的校验,而不是 Agent 名称或提示词内容。每次委派还需定义输入范围、输出格式、预算、deadline、取消传播方式及失败归属。
MCP、Skills 与 A2A:分别看接入对象
Section titled “MCP、Skills 与 A2A:分别看接入对象”MCP 让 Host/Client 与外部 Server 按协议发现和调用能力。工具 Tools 用于执行动作或计算;Resources 提供可读取的数据;Prompts 提供可发现的提示模板。典型路径是 Host 选择可供模型使用的工具,模型提出工具调用,Host 校验参数和权限,再经 MCP Client 调用 Server,并把结果送回模型。协议没有替应用决定是否允许某个用户退某笔订单,也不保证 Server 实现没有副作用。79
MCP 的 JSON Schema 或工具描述能帮助表达参数形状,但并非业务授权。Server 应检查输入、访问控制和频率;Host 对高风险动作应显示操作信息并要求适当确认。HTTP 授权方案与 stdio 环境凭据也不能混成一套配置,不同 transport 应按当前规范和实现版本处理。令牌的受众、权限和委托范围要明确;上游访问令牌不应不加判断地转发给工具下游。服务端还要限制可访问的资源 URI、网络目标和重定向,防止代理被诱导访问内网。10
Skill 是可复用的操作指南、参考材料或辅助文件;它告诉执行者如何处理任务,不是默认可信的程序能力或授权凭据。11 A2A 则面向不同 Agent 系统之间的任务协作和结果交换。12 三者可以组合,但职责不能互相顶替:Skill 指导流程,MCP 接入工具或上下文,A2A 承载 Agent 之间的任务边界。小型单体服务只需要普通函数时,没必要为了“用了 Agent”而全部协议化。
审批、提示注入与执行权限
Section titled “审批、提示注入与执行权限”审批必须绑定将要执行的具体提案,而不是只绑定一句“同意”。提案至少记录主体、商家、对象 ID、动作、金额、币种、业务版本、有效期限和规范化参数摘要。执行时重新验证当前调用者权限、订单状态和审批提案摘要;提案有变化、金额变更或版本过期时重新审批。批准操作本身也要去重,防止双击造成两次推进。长时间等待应把状态持久化并释放 worker 与数据库连接,而不是持锁等人点击。
来自网页、邮件、商品描述或工具响应的文字可能包含提示注入。无论内容写“忽略先前指令”还是“主管已批准退款”,它都只是未经验证的数据,不能升级为可信指令或权限。防护要让模型即使被误导也没有足够权限造成破坏:限制模型看到的敏感数据;工具只开放必要动作;执行前在服务端校验资源、金额和身份;高风险动作绑定审批;约束代码执行网络出口和资源配额;记录审计事件并测试恶意输入。分类器或输出过滤能辅助识别,但不能替代副作用前的策略拦截。13
沙箱解决进程、文件、网络和 CPU 等执行资源边界;业务授权解决谁能对哪个业务对象做什么。容器里运行的代码如果可以调用一个持有全商户权限的退款工具,仍可能造成越权。反过来,订单级授权也不会自动阻止脚本读取本机密钥或耗尽 CPU。需要分别配置执行隔离和工具服务端权限,凭据由服务端按调用上下文注入,不能让模型自行提供权限字段。
一致性、容量控制与补偿语义
Section titled “一致性、容量控制与补偿语义”CAP 讨论网络分区发生时的取舍:无法同时保证所有分区下持续可用并让操作保持线性一致。线性一致性要求操作看起来在调用与响应之间某一时刻生效,并遵守实时先后;可串行化要求并发事务等价于某个串行顺序,但不必满足实时顺序。最终一致性要求在没有新更新、相关更新能够传播等前提下副本最终收敛;它不保证收敛后的值符合业务规则。15 退款额度、幂等操作和审批状态应由权威写入路径维护;报表或商品展示可以接受有限陈旧,但不能拿延迟副本的旧余额来决定是否再退款。
限流限制某段时间的请求速率或额度;Semaphore 限制同时运行的任务数;熔断在依赖持续失败时暂时停止新增调用;隔离保护租户、队列或依赖的资源池;背压让上游跟随下游处理能力。无限队列只会把拒绝变成延迟和内存压力。Agent 工作量还取决于每个 run 中模型调用、并行工具和重试次数,因此需分别设置 run 配额、模型 token/RPM 预算、支付并发和数据库连接上限。若平均每秒到达 2 个任务、每个任务平均运行 30 秒,稳定状态下平均约有 60 个任务在途,这是 Little 定律的粗估,不等于线程或机器数;人审等待不应占用活跃 worker。
两阶段提交(2PC)先让各参与者 prepare,再由协调者决定 commit 或 abort。参与者处于准备状态却联系不到协调者时,可能需要继续持有锁和资源并等待恢复。它要求参与系统支持相应事务协议;普通第三方支付 HTTP API 不能因为调用方加了事务就参加 2PC。
Saga 把跨服务业务拆成本地事务序列,失败时通过业务补偿或前向恢复处理已提交步骤。补偿不是数据库 rollback:邮件可能已发送,退款可能已完成,物流也许已发货;有些效果无法逆转,补偿自身也可能失败。因此补偿要可重试、可审计并设置人工处置状态;可以在不可逆步骤之前先校验与预留,减少失败后的修复范围。14
退款服务:从请求受理到确认终态
Section titled “退款服务:从请求受理到确认终态”假设一个支付允许多次部分退款,服务需要防止重复操作和总额超限。把业务上限记为 cap,已确认退款为 refunded,尚未最终确认但占用额度的申请为 reserved,必须始终维持:
refunded >= 0reserved >= 0refunded + reserved <= capHTTP 请求、模型工具调用和支付操作不能混为一个身份。客户端以商户和支付为作用域提交稳定的业务幂等键;服务保存 refund_id、规范化请求摘要、金额、币种、审批版本、状态和预先生成的 provider_key。同键同参读取现有 operation,同键异参拒绝。真正的新部分退款必须是新的获批业务意图。金额使用精确整数单位并带币种,具体最小单位遵循货币和支付通道契约,而非假定所有币种都以 100 为基数。
接口受理时先验证调用主体、商户与支付归属、金额正值、币种、退款上限和审批版本。随后在一个短数据库事务里插入退款操作,利用唯一约束处理并发;对 payment 记录进行条件更新,只有 cap - refunded - reserved >= amount 才增加 reserved;写入 Outbox 后提交。检查受影响行数,未更新一行就回滚。接到同键请求时先回滚唯一键冲突事务,再查询既有 operation 并比对摘要。数据库事务提交成功才返回“已受理”,并返回稳定 refund_id 供查询。
-- 事务内示意;:amount 等表示应用绑定参数,并非 MySQL 命令行语法-- 操作身份插入、额度预留和 outbox 写入UPDATE paymentsSET reserved_minor = reserved_minor + :amount, version = version + 1WHERE payment_id = :payment_id AND currency = :currency AND refundable_cap_minor - refunded_minor - reserved_minor >= :amount;-- 应用检查 affected_rows = 1;否则回滚整个事务支付调用不放在数据库事务中。持有数据库锁等待网络几秒或几分钟,既占连接又无法把远端纳入本地提交。Outbox relay 把事件送到持久队列;投递可能重复,worker 读取 operation 当前状态,以版本/租约领取工作,再按持久化的 provider_key 调用支付方。租约过期可以阻止旧 worker 改写新版本,但不能撤回已发出的请求。外部请求超时后记录 UNKNOWN,保留预留额度,等待回调或主动查询;只有服务商契约允许时才用同一个键重试。
状态可以表示为 RESERVED → PROCESSING → SUCCEEDED,也可从 PROCESSING 到 UNKNOWN 或经确认的 FAILED_FINAL。UNKNOWN 不是失败的同义词。支付方确认成功时,在一个本地事务中验证状态仍可转换,减少 reserved、增加 refunded、记录通道凭据、更新 operation 并写出后续事件。对同一成功回调重复处理时,不重复增加 refunded。只有能确认通道操作不会再生效的最终拒绝,才释放预留。查询“暂时没有记录”不一定证明原请求永远不会迟到。
支付回调要先验签、校验商户/退款 ID/金额/币种,之后以通道事件 ID 去重,并检查版本和允许的状态转移。回调乱序时不能按最后到达覆盖状态;旧的处理中事件不得倒退已确认成功。回调处理事务只负责本地状态和额度,不应在回调 HTTP 请求中再启动一个未受控的外部退款。定期对账负责发现漏回调和长时间 UNKNOWN;无法确认时让操作留在待核查状态并通知人工,而不是释放额度使系统表面上“恢复正常”。
图中 refunded + reserved <= cap 是本地数据库需维持的不变量。支付调用位于本地事务之外,故状态未知时继续保留额度,待查明事实后再更新。
该状态图表示业务处理规则,不表示某个已部署支付产品的实际实现。回调、查询或人工核查提供证据后才推进终态。
用户批准“订单 A,退款 200 元,版本 v4”,模型执行时生成了“订单 B,退款 300 元”。服务应如何处理?
- A. 只检查用户是否曾经点过批准
- B. 用审批记录中绑定的对象、金额、币种和版本重新校验,不匹配就拒绝并重新审批
- C. 只要 MCP 工具 schema 正确就允许执行
- D. 把新参数保存到 checkpoint 后自动执行
答案与解析
正确答案:B。A 没有绑定批准内容;C 的 schema 只描述参数结构,不授予业务权限;D 的状态持久化也不等于授权。
哪项描述最准确地区分 MCP、Skill 与 A2A?
- A. MCP 提供 Agent 推理,Skill 提供权限,A2A 提供数据库事务
- B. MCP 接入工具/上下文服务,Skill 提供可复用任务指导,A2A 面向 Agent 间任务协作
- C. 三者都是不同名称的 function calling
- D. 使用 A2A 后,工具调用不再需要鉴权
答案与解析
正确答案:B。A 混淆协议与授权;C 忽略不同边界;D 错,跨 Agent 任务传递不替代工具侧鉴权。
网络分区时,退款额度的权威写入节点无法确认自己仍是唯一写入者。较安全的选择是什么?
- A. 两侧都接受退款,之后用最后写入值合并
- B. 继续从缓存读额度并发起支付
- C. 暂停相关写入或拒绝受影响请求,避免重复分配额度
- D. 让 Agent 多调用几次模型,投票决定余额
答案与解析
正确答案:C。A 可能双重预留;B 的缓存不是权威写入;D 模型投票与业务事实无关。某些展示读取可降级,但涉及退款额度的写操作要守住唯一权威。
请求平均每秒到达 2 个,平均服务时间 30 秒,按 Little 定律得到的近似在途任务数是多少?
- A. 2
- B. 15
- C. 30
- D. 60
答案与解析
正确答案:D。平均在途数约为到达率 × 平均停留时间,即 2 × 30 = 60。它不是容量上限或所需线程数。
Outbox 事件被重复投递,而消费者后续会调用支付方。哪项做法正确?
- A. 只在 Inbox 记录事件已处理,之后不必管支付结果
- B. 事件对应稳定退款 operation,消费者按当前状态推进,并用持久化下游键和查询处理外部副作用
- C. 每次收到重复事件都生成新 provider key,保证一次一键
- D. 消费者在数据库事务中保持行锁直到支付响应返回
答案与解析
正确答案:B。A 把本地去重误当外部成功;C 会把同一意图拆成多个远端操作;D 不能实现跨系统原子性,还会长期占用锁和连接。
以下哪项最准确地描述 Saga 补偿?
- A. 自动撤销所有已经提交的外部副作用,效果等同数据库 rollback
- B. 一组业务定义的后续操作,用于恢复或推进到可接受状态;补偿也可能失败
- C. 只要选择 Saga 就不需要持久化中间状态
- D. Saga 会让所有参与服务共享一个 ACID 事务
答案与解析
正确答案:B。A 夸大可逆性;C 忽略中间状态和恢复;D 把 Saga 与分布式 ACID 事务混淆。
说明 Agent-as-tool 与 handoff 在控制流上的区别,并给出拆分成多个 Agent 的两个合理条件,以及一个不能当作安全隔离的理由。
参考答案与评分点
Agent-as-tool 是父 Agent 调用子 Agent 并收回结果后继续控制;handoff 把后续任务控制权交给另一个 Agent。拆分可因独立任务能并行、需要隔离专业上下文或权限确实不同而合理;Agent 的提示词和上下文边界不构成业务授权,工具服务端仍须验权。
评分:1 分区分控制流;1 分写出并行或上下文隔离条件;1 分写出另一个有效条件或协调成本;1 分指出 Agent 边界不等于授权边界。
用户批准退款 200 元后,订单状态变更且模型尝试退 300 元。执行服务需重新验证哪些内容?
参考答案与评分点
服务应核对认证主体、商户和订单对象、退款动作、金额与币种、审批绑定的参数摘要和版本、有效期及当前订单/退款额度状态。任何批准范围变化都拒绝,要求生成新提案并重新审批。批准记录是权威数据,不从检索文档或模型上下文推断。
评分:1 分核对对象与主体;1 分核对金额/币种/动作;1 分核对版本、有效期或摘要;1 分说明变化应拒绝并重新审批。
解释退款核心不变量如何在两笔并发退款申请下保持成立,并说明支付请求为什么放在事务之外。
参考答案与评分点
本地事务插入 operation 并对 payment 行进行带额度条件的原子更新,只有 cap - refunded - reserved >= amount 时才能增加 reserved;竞争请求由数据库序列化该行更新,失败事务回滚。确认成功时把 reserved 转到 refunded。外部支付调用放在事务外,避免长时间锁定数据库;本地提交无法与独立支付方原子提交,外部结果要经 operation 状态、稳定键、查询和回调处理。
评分:1 分写对不变量;1 分用数据库原子条件或锁;1 分说明失败回滚/成功转换;1 分指出本地事务不覆盖支付方。
支付请求超时、回调未到,之后收到一条重复成功回调。写出服务的处理步骤和仍无法保证的边界。
参考答案与评分点
超时先记录 UNKNOWN 并保留预留;用原 provider key 查询状态,或在契约允许时同键重试。回调验签、校验 operation 与金额币种,以 provider event ID 去重;在本地事务里检查允许的状态转换,将 reserved 转入 refunded 并更新操作,重复事件不重复增加金额。若支付方无可靠幂等、查询或可核查凭据,系统无法凭本地数据库证明远端 exactly-once,应暂停、对账或人工核验。
评分:1 分未知不视作失败且保留预留;1 分同键查询/重试;1 分回调验证去重并原子更新;1 分说明下游契约不足时不承诺 exactly-once。
- MCP Server 的工具调用与安全建议:Tools、Resources、Prompts、Authorization。
- Skill 的定义与 A2A 的任务协作边界:Agent Skills Specification、A2A Overview。
- Prompt Injection 的风险与缓解:OWASP GenAI Security。
- Saga 编排与补偿步骤:AWS Saga Orchestration。
- 线性一致与可串行化的语义:Jepsen Linearizability、Jepsen Serializability。
Sources
Section titled “Sources”下面保留原报告的题目和口述参考答案。先自行作答,再展开查看。
AG15|什么时候需要多 Agent?Handoff 与 Agent-as-tool 呢?〔P0〕
口述答案
先用单 Agent 或显式 Workflow。只有独立子任务能并行、上下文确实需要隔离、职责分工能减少干扰,并且质量收益超过协调成本时,才拆多个 Agent。拆分后必须明确谁拥有任务、共享什么状态、谁能写业务数据、预算如何分配、失败由谁处理。
Agent-as-tool 像子调用:主 Agent 委派任务,收回结果后继续控制流程;Handoff 更像交接:当前控制权转给另一个 Agent,交接哪些历史与身份由系统配置。两者都不是安全隔离边界,子 Agent 的权限仍需独立限制。
追问怎么接
“给订单、政策、退款各配一个 Agent 好不好?”名称对应业务域不构成拆分理由。只读查询可能几个函数就够;退款需要确定性服务,不一定需要另一个自由规划模型。“结果冲突谁决定?”明确定义合并规则与证据优先级,不能默认多数投票就是真相。
不要这样答:“多 Agent 肯定更强、更快”,或“子 Agent 看不到主提示词,所以一定无法越权”。
依据与延伸:SDK-Agents、Agent-Patterns、OWASP-Agency。
AG16|MCP 和 Function Calling 的区别是什么?〔P0〕
口述答案
Function Calling 是模型与应用之间表达“调用哪个工具、传什么参数”的接口;MCP 是应用与外部工具/上下文服务之间的标准化协议。Host 是承载模型交互的应用,Client 是 Host 中的连接组件,Server 提供工具或数据。
常见链路是:Host 经 MCP 发现工具 → 把工具定义适配给模型 → 模型产生调用 → Host 校验后经 MCP 调用 Server → 结果回到模型。MCP 不替模型做规划,也不自动运行 Agent 循环。只有几个内部函数时不必强行上 MCP;需要多个客户端复用同一服务时,它更有价值。
追问怎么接
“MCP 只有 Tools 吗?”还有 Resources 与 Prompts 等能力,分别对应数据资源和提示模板,不等同于任意可执行函数。“Server 说某工具是只读就可信?”不自动可信;工具元数据和实际代码行为都必须按来源管理。
不要这样答:“MCP 是 Agent 的大脑”“接 MCP 就不需要 function calling”“MCP Server 就是模型服务”。
AG17|MCP 授权、传输和版本要准备到什么程度?〔P1〕
口述答案
需要讲清边界,不需要背每个 JSON 字段。MCP 规定通信、能力与授权相关契约,但业务服务仍要检查当前调用者能否访问某个商家、订单和动作。标准化 OAuth 或拿到 access token,不代表得到所有业务权限。
本文阅读的 2026-07-28 规范采用无状态、自包含请求的核心;不能把早期教程中所有连接状态假设当作当前规范。真正集成时检查客户端、Server 和扩展支持的版本交集,按具体 transport 与授权模式实现,不说“所有版本都一样”。
追问怎么接
“最重要的安全点?”校验令牌目标资源/受众和权限,不把上游 token 任意转发给下游;避免 confused deputy;对 Server 地址、重定向和网络访问做限制,防止 SSRF。令牌交换和授权链在服务端处理,不把长期密钥放进模型上下文。
不要这样答:“MCP 没有安全机制”,以及相反的“有 OAuth 就不需要资源级鉴权”。
依据与延伸:MCP、MCP-Auth、MCP-Security。
AG18|Skills、MCP、A2A 分别是什么?〔P2〕
口述答案
Skill 是可复用的任务知识包,通常包含说明、参考资料及可能的脚本,通过按需加载减少一开始的上下文负担;它不是训练出来的新模型,也不是默认受信任的可执行权限。MCP 解决工具和上下文服务的互操作;A2A 关注独立 Agent 之间的任务与结果协作。
可以把 Skill 理解为“怎样完成某类任务的材料”,工具是“实际能做的动作”,MCP 是一种接入这些能力的协议,A2A 是跨 Agent 协作接口。这些层可以组合,但小团队内部调用不必全部协议化。
追问怎么接
“Skill 里有脚本,能直接执行吗?”必须经过同样的代码与工具权限边界;文档来源、版本和脚本依赖需要管理。“面试要写 A2A Server 吗?”当前准备无需,能说明用途、额外复杂度与适用场景即可。
不要这样答:“Skills 是微调”“MCP 和 A2A 谁会取代谁”。
AG22|如何防 Prompt Injection?Guardrail 能保证安全吗?〔P0〕
口述答案
外部文档、商品描述、邮件和工具结果可能带有试图改变指令的内容。它们是数据,不能因此获得指令或授权地位。防御需要分层:标记来源、限制可见敏感数据、最小权限工具、参数与资源级校验、敏感动作审批、网络出口限制及攻击测试。
模型分类器和输出检查可以降低风险,但不是安全证明。尤其是输出 guardrail 在工具已执行后才发现问题,不能撤销退款;关键权限和策略必须在副作用前阻断。并行跑安全检查时,要明确高风险动作是否会抢先执行。
追问怎么接
“让 system prompt 写不要听文档就够了吗?”不够,它不能代替权限边界。“注入内容完全删除是否可行?”无法保证所有恶意内容都被检测,且可能破坏正常证据。设计应使模型被误导时也难以造成越权副作用。
不要这样答:“有一个审核模型所以是安全的”“输出拒绝了,就证明工具没做危险操作”。
AG23|沙箱安全与业务工具安全有什么区别?〔P0〕
口述答案
沙箱约束生成代码能接触的进程、文件、网络和计算资源;业务授权约束调用者能对哪些业务对象做哪些动作。把代码放进容器/Wasm,不会让一个持有管理员退款凭据的工具变安全;反过来,严格的订单权限也不能阻止未经限制的代码耗尽 CPU 或读取宿主密钥。
我的设计分两层:代码执行采用按任务隔离、受限文件/网络、资源预算与可回收进程树;工具网关在服务端注入最小权限身份,对每次业务操作验权和审计。密钥不通过模型生成参数传递。
追问怎么接
“容器就绝对安全吗?”不作这种承诺,隔离机制依赖威胁模型与宿主配置。“取消后怎么办?”停止派发新动作,传播取消并终止允许终止的执行单元;已发生的外部副作用仍需状态核查,不能假装没发生。
**不要这样答:**把你熟悉的 sandbox 当作 Agent 安全的全部,忽略持合法凭据的越权业务调用。
依据与延伸:OWASP-Agency、MCP-Security、Programmatic。
DS04|CAP、线性一致性、可串行化、最终一致性怎么区分?〔P1〕
口述答案
CAP 讨论发生网络分区时,线性一致性与让所有非故障节点持续完成请求的可用性无法同时保证;不是日常任挑两个标签。是否拒绝一部分请求,要按具体业务对象和操作决定,不能把整家公司简单归类为 CP 或 AP。
线性一致性关注操作看起来原子发生且遵守实时先后;可串行化关注并发事务等价于某个串行顺序,不必自动满足实时顺序。最终一致性也不保证“最终就是正确业务状态”,还需要明确冲突解决、重试和收敛规则。
追问怎么接
“退款选择什么?”核心额度与操作身份优先保证正确性,不确定时宁可暂停部分写;商品展示可允许有限陈旧。“主从复制就是强一致?”不一定,要看读写路径、确认和故障切换。“有共识还要幂等?”共识解决复制状态的一致性,不替客户端和外部服务定义请求身份。
不要这样答:“CAP 的 C 就是 ACID 的 C”“强一致系统就不会出现业务重复操作”。
依据与延伸:Linearizable、Serializable、Redis-Repl。
DS05|限流、熔断、隔离、背压与容量估算怎么讲?〔P0〕
口述答案
限流约束单位时间或资源预算的请求,Semaphore 约束在途并发;熔断在下游持续异常时暂时减少调用;隔离避免一个租户或依赖拖垮全部任务;背压要求上游按处理能力放慢。队列本身不创造容量,需要有界长度、超时和明确的拒绝/降级策略。
Agent 不能只按用户 QPS 配额:一个 run 可能多次调用模型、并行多个工具,失败还会重试。需要分别预算 run、模型 RPM/TPM、工具并发和数据库连接。容量估算先算平均需求,再用真实尾延迟、突发和失效余量验证。
追问怎么接
“平均每秒 2 个任务,平均执行 30 秒,需要多少在途能力?”稳态下平均约 60 个在途任务,这是到达率×平均停留时间的估算,不是线程数或 GPU 数,也不是 p95 容量上限。人审等待不应占着活动 worker;活跃调用与等待 run 分别算。
不要这样答:“堆更多 worker 就会更快”“把队列长度开无限大就不丢请求”。
依据与延伸:AWS-Retry、Rate-Limits、Node-Blocking。
DS06|2PC、Saga、补偿怎么选择?〔P1〕
口述答案
2PC 通过参与者准备与协调提交实现分布式提交决策,但要求参与系统支持相应协议,并可能长时间占用资源或在故障下等待。Saga 把业务拆成一串已提交的本地事务,失败时执行业务补偿;它不提供与单一 ACID 事务相同的隔离和自动回滚。
退款发起后“补偿”通常不能简单理解为把钱偷偷再扣回来。优先在不可逆步骤前完成校验与预留,未知结果先核查;可逆步骤定义明确补偿,补偿也要幂等、能重试,并有最终人工兜底。
追问怎么接
“有 Saga 就没有中间状态问题?”仍有,并发流程可能观察到中间状态;用预留/冻结/业务锁定等语义减少冲突。“补偿失败怎么办?”持久记录、重试、告警和人工处理,不把它吞掉当整个任务已经回滚。
不要这样答:“Saga 等于跨库 rollback”“所有外部 API 都可以放进 2PC”。
依据与延伸:Saga、Temporal-Activity、Stripe-Idem。