AI 生成代码库的安全性、性能与可靠性
一本实用指南,介绍如何评估 AI 生成代码库的安全性、性能与可靠性,包含审查、测试与监控的清单。

对 AI 生成代码的预期
“AI 生成代码”在不同团队和工具链中可能意味着完全不同的事情。对一些人来说,它是在现有模块中补全的几行代码;对另一些人来说,它可能是完整的端点、数据模型、迁移、测试桩,或由提示生成的大规模重构。在评估质量之前,先写下你仓库里哪些算是 AI 生成:片段、完整函数、新服务、基础设施代码,或“AI 辅助”重写。
关键预期:AI 的输出是一个草稿,不是保证。它可以可读性很高,但仍然遗漏边界情况、误用库、跳过认证检查,或引入微妙的性能瓶颈。把它当成来自节奏很快的初级同事的代码:能提高速度,但需要审查、测试和明确的验收标准。
如果你在使用一种“vibe-coding”式的工作流(例如,在像 Koder.ai 这样的平台里从聊天提示生成完整功能——前端 React、后端 Go + PostgreSQL,或一个 Flutter 移动应用),这种心态就更重要了。生成的面积越大,越需要把“完成”定义为不仅仅是“能编译”。
为什么需要明确的标准
如果不去请求并验证,安全、性能和可靠性不会可靠地“出现在”生成代码中。AI 倾向于优化出看起来合理的模式,而不是针对你的威胁模型、流量形态、故障模式或合规义务。没有明确标准,团队常常合并在演示中正常但在真实流量或对抗输入下会失败的代码。
三大支柱(以及它们如何相互关联)
- 安全:防止被滥用:输入校验、正确的认证/授权、安全的默认值,以及对秘密和数据的谨慎处理。
- 性能:在预期规模下的高效性:可预测的延迟、避免不必要的 I/O、控制资源使用。
- 可靠性:随时间保持正确:处理部分失败、重试、幂等性,以及在依赖变慢或宕机时的合理行为。
在实践中,这些会互相重叠。例如,速率限制既提高安全性又提高可靠性;缓存可以提升性能,但若在用户之间泄露数据则损害安全;严格的超时提高可靠性,但可能暴露出需要加固的新错误处理路径。
本节设定基本心态:AI 加速写代码,但“可上线”是你定义并持续验证的质量门槛。
生成代码中的常见风险模式
AI 生成的代码通常看起来整洁自信,但最常见的问题不是风格上的——而是判断力的缺失。模型可以生成看似合理的实现,能编译甚至通过基础测试,同时悄悄忽略你的系统依赖的上下文。
常见的风险领域
审查中反复出现的类别:
- 输入处理:缺少校验、不安全的解析、信任客户端提供的 ID,或直接构造 SQL/JSON/HTML 字符串。
- 认证与授权:混淆“已登录”和“有权限”,跳过角色检查,或只在部分端点应用检查。
- 错误处理:在错误消息中泄露内部细节、吞掉异常、在部分失败时返回成功,或使用过宽的
catch块掩盖真实问题。 - 并发与状态:竞态条件、非线程安全的缓存、天真的锁导致死锁,以及关于单请求执行的错误假设。
漏洞中的“未知的未知”
生成代码可能带有隐含假设:时区总是 UTC、ID 总是数字、请求总是格式正确、网络调用总是快速、重试总是安全。它还可能包含部分实现——被桩化的安全检查、带有 TODO 的路径,或返回默认数据而不是安全失败的回退分支。
无上下文复制模式
一种常见的失败模式是借用在别处正确的模式,但在这里是错误的:重用哈希助手却没有使用正确参数、应用不匹配输出上下文的通用清理器,或采用会无意中放大负载(和成本)的重试循环。
所有权不会转移
即便代码是生成的,人类仍对其在生产中的行为负责。把 AI 输出当作草稿:你要承担威胁模型、边界情况和后果的责任。
从简单的威胁模型开始
AI 生成的代码看起来自信且完整——这会让人容易跳过最基本的问题:“我们在保护什么,防范谁?”一个简单的威胁模型是一个简短的、明白易行的习惯,可以在代码固定之前把安全决策显式化。
定义资产、行为者和信任边界
先把会受损害时有影响的资产命名:
- 数据:客户的 PII、认证令牌、API 密钥、发票
- 资金流动:支付、退款、积分、支付给付
- 管理员操作:用户角色变更、功能开关、数据导出
- 可用性:在不被下线的情况下提供请求的能力
然后列出行为者:普通用户、管理员、支持人员、外部服务和攻击者(凭证填充、欺诈者、机器人)。
最后描述 信任边界:浏览器 ↔ 后端、后端 ↔ 数据库、后端 ↔ 第三方 API、内部服务 ↔ 公网。如果 AI 提议跨越这些边界的“快速”捷径(例如公开端点直接访问数据库),应立即标记。
编码前的轻量检查表
保持足够简短以便实际使用:
- 恶意用户能用该功能造成的最坏后果是什么?
- 哪些输入跨越信任边界(表单、Webhook、头、文件)?
- 哪些操作需要授权(尤其是管理员和资金相关操作)?
- 哪些事件必须被记录并触发告警(认证失败、高价值操作)?
- 安全的失败模式是什么(默认拒绝、速率限制、回滚)?
在评审者可见处记录决策
把答案记录在 PR 描述中,或当选择是长期性的(例如令牌格式、Webhook 验证方式)时创建简短的 ADR(架构决策记录)。未来的审查者就能判断 AI 生成的改动是否仍与初始意图一致——以及哪些风险是被有意识接受的。
代码审查的安全清单
AI 生成的代码可能看起来干净一致,但仍隐藏安全陷阱——尤其是在默认设置、错误处理和访问控制方面。审查时关注的重点不是风格,而是“攻击者可以做什么?”
捕捉大多数问题的快速检查项
- 检查安全默认值: 默认拒绝、最小权限、最小暴露面。
- 验证必要位置的输入校验和输出编码。
- 确保秘密绝不硬编码, 通过环境变量或密钥管理器加载。
- 确认安全的错误信息(不要在响应中返回堆栈或敏感数据)。
- 验证授权(authz)在服务端生效, 而非仅在 UI 层面。
审查 diff 时应注意的点
信任边界。 识别数据进入系统的位置(HTTP 请求、Webhook、队列、文件)。确保在边界处进行校验,而不是“某处稍后再做”。对于输出,检查编码是否与上下文匹配(HTML、SQL、Shell、日志)。
认证 vs. 授权。 AI 代码常包含 isLoggedIn 检查,但遗漏资源级别的强制。验证每个敏感操作都检查谁可以对哪个对象操作(例如 URL 中的 userId 必须通过权限校验,而不是仅仅存在)。
秘密与配置。 确认 API 密钥、令牌和连接字符串不在源码、示例配置、日志或测试中。同时检查“调试模式”默认未开启。
错误处理和日志。 确保失败不会返回原始异常、堆栈或 SQL 错误或内部 ID。日志应有用且不泄露凭证、访问令牌或个人数据。
有助于审查的小习惯
为每个高风险路径要求一个负面测试(未授权访问、无效输入、过期令牌)。如果代码无法以这种方式被测试,往往说明安全边界不清晰。
依赖与供应链安全
AI 生成代码常常通过添加包来“解决”问题。这会悄然扩大你的攻击面:更多维护者、更多更新、更多你没有明确选择的传递依赖。
锁定你发布的内容
从让依赖选择变得有意开始。
- 固定版本(并提交锁文件),以便构建在机器和 CI 间可重现。
- 优先使用受信任的注册表集合(如果可能,内部镜像)。
- 把任何新包当作变更来处理:审查其必要性、维护者、许可证是否合适,以及安全历史。
一个简单规则管用:没有在 PR 描述中写出简短理由的,不允许新增依赖。 如果 AI 建议使用某库,先问标准库或已批准的现有包是否已覆盖需求。
在 CI 中加入扫描——并定义后续流程
自动化扫描只有在发现后能触发相应动作时才有价值。添加:
- SCA(软件成分分析)来标出已知漏洞依赖
- 密钥扫描以捕捉在生成代码和配置中泄露的密钥/令牌
然后定义处理规则:哪些严重程度会阻止合并、哪些可以用 issue 时间盒解决、谁批准例外。把这些规则写入贡献指南并链接(例如 /docs/contributing)。
关注传递风险和依赖膨胀
很多事故来自间接拉入的传递依赖。审查 PR 中的 lockfile diff,定期清理未使用的包——AI 代码可能导入“以防万一”的辅助工具但从不使用它们。
记录更新流程
写明更新如何进行(定期的版本更新 PR、自动化工具或人工),以及谁批准依赖变更。明确的责任能防止易受攻击的过时包滞留在生产中。
性能:什么才是“好”
性能不是“应用感觉快”。它是与你产品实际使用方式和可承受成本相匹配的一组可测量目标。AI 生成的代码常能通过测试且看起来整洁,但仍可能消耗大量 CPU、过度访问数据库或不必要地分配内存。
设定明确的性能目标
在微调之前以数字定义“好”。常见目标包括:
- 响应时间: 关键端点或用户动作的 p95 和 p99 延迟
- 吞吐量: 预期峰值下的每秒请求数或每分钟作业数
- 资源使用: 在负载下的 CPU、内存、磁盘 I/O、网络 I/O
- 成本: 每 1,000 次请求或每个作业/活跃用户的云花费
这些目标应与真实工作负载(你的“常用路径”及常见突发)关联,而不是单一合成基准。
瓶颈通常藏在哪里
在 AI 生成的代码库中,低效常出现在可预测的位置:
- 数据库调用: 聊天式访问模式、缺少索引、重复查询
- N+1 查询: 在循环中逐行获取相关数据
- 文件或 JSON 解析: 重复解析大负载或使用重量级库
- 紧密循环: 每次迭代不必要的工作、糟糕的数据结构、多余的分配
生成的代码通常“从构造上正确”但默认不是“高效”。模型倾向于选择可读的、通用的方法(额外抽象层、重复转换、无界分页),除非你指定约束。
优化前先做剖析
避免猜测。在类似生产的环境中先做剖析与测量:
- 使用应用剖析器(CPU/内存)和数据库时间的查询追踪。
- 收集延迟分位数与最慢端点;识别前 2–3 个热点。
- 每次只做一个改动并重新测量以确认影响。
如果你不能对照目标显示前后改进,那不是优化——只是变更。
实用的性能护栏
AI 生成代码常“能工作”但会悄然消耗时间和成本:额外的数据库往返、意外的 N+1 查询、对大数据集的无界循环,或永不停的重试。护栏能让性能成为默认而不是事后的英雄行为。
带退出方案地使用缓存
缓存可以掩盖慢路径,但也可能永远服务陈旧数据。仅在有明确失效策略(基于时间的 TTL、事件驱动失效或版本化 key)时使用缓存。若你不能解释缓存值如何被刷新,就不要缓存。
让等待变得有意图
确认超时、重试和退避是经过考虑的(不是无限等待)。每个外部调用——HTTP、数据库、队列或第三方 API——都应有:
- 合理的超时
- 有限的重试
- 带抖动的指数退避
- 明确的失败模式(回退、部分响应或快速错误)
这能防止在负载下“慢失败”占用资源。
尊重异步边界
避免在异步路径中使用阻塞调用;检查线程使用情况。常见问题包括同步文件读取、在事件循环上做 CPU 密集型工作,或在异步处理器中使用阻塞库。如果需要大量计算,应卸载到(工作池、后台作业或独立服务)。
提前为大数据设计
确保批量操作与分页支持大数据。任何返回集合的端点都应支持限制和游标,后台作业应分块处理。如果查询会随用户数据增长,请默认它会增长。
在发布前捕获回归
把性能测试加入 CI,以捕捉回归。让它们小而有意义:几个热点端点、代表性数据集和阈值(延迟分位数、内存、查询计数)。把失败当作测试失败——调查并修复,而不是“重跑到绿色”。
可靠性:在真实条件下的正确性
可靠性不仅仅是“没有崩溃”。对 AI 生成代码而言,它意味着系统在肮脏输入、间歇性故障和真实用户行为下仍能产出正确结果——若不能,也要以可控方式失败。
事先定义可靠性结果
在审查实现细节前,先就关键路径的“正确”达成一致:
- 正确结果: 写入正确的数据、返回正确的响应、不发生静默截断或四舍五入惊喜。
- 优雅失败: 明确的错误信息、安全的默认值、在出错时不破坏状态。
- 可预测的恢复: 重试、重放和重启不会制造重复或偏差。
这些结果为审查 AI 写的逻辑提供评判标准——那些看似合理但掩盖边界情况的实现可以据此评估。
对可重试操作的幂等性
AI 生成的处理器常“只做事然后返回 200”。对于支付、作业处理和 webhook 摄取来说,这很危险,因为重试是常态。
检查代码是否支持幂等性:
- 稳定的幂等键(请求 ID、事件 ID、支付意图 ID)
- 持久化的“已处理”记录
- 对重复交付的安全行为(不重复扣款、不重复发送邮件、不重复写入行)
明确事务与一致性
如果流程涉及数据库、队列和缓存,验证一致性规则在代码中明确表达——不是被假定的。
查找:
- 多次写入必须同时成功或失败时的数据库事务
- “写状态”与“发布事件”之间的明确顺序(或使用 outbox 模式)
- 能容忍丢失更新的缓存失效策略
处理服务间的部分失败
分布式系统会部分失败。确认代码能处理“DB 写入成功但事件发布失败”或“HTTP 调用超时但远端已成功”这类场景。
偏好超时、有界重试和补偿动作,而不是无限重试或静默忽略。在测试中注明需要验证这些情况(可参见 /blog/testing-strategy-that-catches-ai-mistakes)。
能捕捉 AI 错误的测试策略
AI 生成的代码常看起来“完整”但隐藏漏洞:漏掉边界情况、对输入过于乐观、未覆盖的错误路径。良好的测试策略不是测试一切,而是测试那些会以意想不到方式失败的部分。
构建分层测试集
从逻辑的单元测试开始,然后在真实系统可能与 mock 行为不同的地方加入集成测试。
- 单元测试覆盖逻辑,集成测试覆盖数据库/队列/外部 API
- 使用逼真的夹具,避免掩盖错误的脆弱 mock
集成测试是 AI 写的粘合代码最常出问题的地方:错误的 SQL 假设、不正确的重试行为或错误建模的 API 响应。
故意测试“不开心路径”
AI 代码经常对失败处理描述不足。加入负面测试以证明系统能安全、可预测地响应:
- 包括无效输入、认证失败、超时、空状态的负面测试
让这些测试断言重要的结果:正确的 HTTP 状态、不在错误信息中泄露数据、重试的幂等性和优雅回退。
对输入密集的代码使用生成测试
当组件解析输入、构造查询或转换用户数据时,传统示例会错过奇怪组合。
- 在适用时为输入密集的组件加入基于属性的测试或模糊测试
属性测试对捕捉边界错误(长度限制、编码问题、意外的 null)非常有效,而这些往往是 AI 实现忽视的。
覆盖率:设定下限,然后关注风险
覆盖率数字可作为最低门槛,而不是终点。
- 定义最低覆盖率目标,但优先覆盖高风险路径
优先测试认证/授权决策、数据校验、资金/积分、删除流程和重试/超时逻辑。如果不确定哪些是“高风险”,把请求路径从公开端点追踪到数据库写入,测试沿途分支。
可观测性与事件准备
AI 生成的代码可能看起来“完成”,但运维起来很难。团队在生产中最常被打击的不是缺失功能——而是缺少可视化。可观测性能把意外事件变成常规修复。
可实际使用的日志
使结构化日志成为必选项。纯文本日志适用于本地开发,但当多个服务和部署参与时,它们不再适用。
要求:
- 请求 ID(跨服务传播并包含在每行日志中)
- 关键上下文字段:用户/账户 ID(在适当时)、端点、方法、状态码、延迟和错误类型
- 明确的严重度等级(debug/info/warn/error)并保持一致含义
目标是通过单个请求 ID 能回答“发生了什么、在哪里、为什么”,而无需猜测。
与真实故障匹配的指标
日志解释“为什么”;指标告诉你“什么时候”开始退化。
加入以下指标:
- 每个端点或作业类型的延迟(p50/p95/p99)
- 错误率(5xx、重试、超时、失败作业)
- 饱和度:CPU、内存、线程/工作池使用率
- 队列深度/积压(用于异步处理)
AI 生成的代码常引入隐藏低效(额外查询、无界循环、聊天式网络调用)。饱和度和队列深度能尽早发现这些问题。
能促成行动的告警
告警应指向一个决策,而不是仅仅一张图。避免噪声阈值(例如“CPU > 70%”),除非它与用户影响相关联。
良好告警设计:
- 类似 SLO 的信号:“p95 延迟 > X 持续 10 分钟”或“错误率 > Y%”
- 明确归属:谁会被呼叫 vs 谁被通知
- 演练链接:包含简短的“首要检查”与运行手册链接
在预发布环境或计划演习中测试告警。如果你不能验证告警能触发并可操作,那它不是告警——只是一个希望。
运行手册:未来的你会感谢你
为关键路径写轻量运行手册:
- 首先检查什么(仪表板、最近部署、依赖状态)
- 如何缓解(关闭功能开关、扩容、禁用后台作业)
- 如何回滚(确切命令/流程、制品存放处)
- 通知谁(值班、产品负责人、事件频道)
把运行手册放在靠近代码与流程的位置——例如在仓库或内部文档中、并从 /blog/ 与 CI/CD 管道链接——以便在系统变化时一起更新。
安全、可重复发布的 CI/CD 控件
AI 生成代码能提高吞吐,但也会增加变异:小改动可能引入安全问题、性能问题或微妙的正确性错误。纪律化的 CI/CD 管道能把这些变异变成可管理的事项。
当一个工具能快速生成并部署(例如 Koder.ai 提供内建部署/托管、自定义域和快照/回滚能力)时,你的 CI/CD 门控与回滚流程也应该同样快速且标准化——这样速度不会以牺牲安全为代价。
在每次变更上强制“质量门”
把流水线当作合并与发布的最低门槛——不要为“快速修复”破例。典型门包括:
- 格式化 + lint 保持差异可读并防止常见错误。
- 单元 + 集成测试 明确的通过/失败标准(不允许不稳定测试)。
- 安全检查: SAST、密钥扫描、依赖漏洞扫描。
- 构建可重现性: 固定工具版本、锁定依赖、确定性构建产物。
若某项检查重要,就把它设为阻塞;若噪声太大,就调整而非忽视它。
逐步发布而非一次性大跳
偏好受控放量而非“一次性全部上线”:
- 功能开关 用于风险较大的行为变更。
- 金丝雀发布(canary) 针对少量流量。
- 蓝绿部署(平台支持时)。
定义自动回滚触发器(错误率、延迟、饱和度),以便在用户感知到影响前停止放量。
让回滚变得平凡——并加以演练
回滚计划只有在能快速执行时才真实。尽量让数据库迁移可逆,除非你有经过测试的前向修复计划。定期在安全环境中做“回滚演练”。
跟踪变更与审批人
要求 PR 模板记录意图、风险与测试说明。为发布维护轻量变更日志,并使用明确的审批规则(例如常规改动至少一位审阅者,安全敏感区域两位)。欲了解更深入的审查工作流,请参见 /blog/code-review-checklist。
对“可上线”的实用定义
AI 生成代码的“可上线”不应意味着“能在我机器上跑”。它意味着代码可由团队安全地运维、修改并信任——在真实流量、真实故障和真实截止时间下也是如此。
不可妥协项(最低门槛)
在任何 AI 生成特性上线前,这四项必须为真:
- 已完成安全审查: 已记录威胁模型假设、识别出高风险输入,并有人审查认证、数据访问与秘密处理。
- 测试通过(并有意义): 核心行为的单元 + 集成覆盖,加上对最可能被滥用的至少一个负面测试。
- 已就绪监控: 关键指标、日志与告警覆盖用户影响(错误、延迟)和业务关键路径。
- 可回滚: 能快速回滚发布(功能开关或已知良好构建),无需“英雄式”操作。
所有权:谁承担告警?
AI 会写代码,但不能拥有它。为每个生成组件指定明确的负责人:
- 服务/团队负责人: 负责修复、值班与后续加固。
- 依赖负责人: 负责更新库、审查安全通告并维护对第三方包的信任。
若所有权不明确,它就不是可上线的。
团队今天就能采用的轻量清单
保持简短以便在审查时实际使用:
- 输入已校验;authz 检查明确;代码或日志中无秘密。
- 失败模式已记录(超时、重试、限制)且默认安全设置就位。
- 测试覆盖了常用路径 + 边界情况;CI 绿色通过。
- 仪表盘/告警存在:错误率、延迟与饱和度。
- 依赖已固定并完成审查;注明升级路径。
你的前 30 天:基线 → 测量 → 收紧
- 第 1–7 天: 做基线安全扫描结果、性能预算和可靠性 SLO。
- 第 8–21 天: 补齐缺失测试、关键告警和依赖固定。
- 第 22–30 天: 收紧 CI/CD 门(阻止失败测试、高危漏洞和缺失可观测性的合并),然后重新测量并迭代。
这个定义让“可上线”具体化——减少争论和意外。
常见问题
什么算是真实代码库中的“AI 生成代码”?
AI 生成的代码是指那些其结构或逻辑在很大程度上由模型根据提示产生的任何改动——无论是几行自动补全、一个完整函数,还是整个服务脚手架。
一个实用规则:如果没有这个工具你不会那样写,就把它当作 AI 生成的代码来处理,应用相同的审查和测试标准。
我们应该默认把 AI 生成的代码当作可直接上线吗?
把 AI 输出当作一个草稿:它可能可读,但仍然有错误。
像对待一位节奏很快的初级同事一样使用它:
- 要求有人工审查并依据明确标准进行验证
- 添加测试(特别是负面测试)
- 在合并前验证安全/性能/可靠性假设
为什么我们需要为 AI 生成的改动制定明确的验收标准?
因为安全、性能和可靠性很少会“偶然”出现在生成代码中。
如果你不指定目标(威胁模型、延迟预算、失败行为),模型会优化出看起来合理的模式——而不是针对你的流量、合规需求或失败模式进行优化。
审核者应注意哪些最常见的风险模式?
重点关注反复出现的漏洞:
- 缺少输入校验或不安全的字符串构造(SQL/JSON/HTML)
- 仅验证“已登录”但未验证“是否有权限”(缺失 authz)
- 泄露详细错误或吞掉异常的错误处理
- 并发问题(竞态、非线程安全缓存)
还要扫描部分实现,如包含 TODO 的分支或默默放开的失败策略。
在合并 AI 生成代码前我们可以应用什么简单的威胁模型?
从小处着手并保持可执行性:
- 资产:如果被破坏会造成损失的对象(PII、令牌、支付、管理员操作、可用性)
- 行为者:用户、管理员、内部服务、攻击者/机器人
- 信任边界:浏览器↔后端、后端↔数据库、后端↔第三方
然后问句:“恶意用户在这个功能上能做的最坏的事情是什么?”
审查生成代码时有哪些实用的安全检查清单?
关注几个高信号检查点:
- 默认拒绝与最小权限原则
- 在边界处校验输入;按上下文对输出进行编码
- 对每个敏感操作在服务端强制执行授权(authz)
- 不要在代码、配置或日志中放置密钥
- 返回安全的错误(不要把堆栈或内部 ID 返回给客户端)
对最危险路径至少要求一个负面测试(未授权、无效输入、过期令牌)。
我们如何减少 AI 建议引入的依赖链与供应链风险?
由于模型可能通过添加第三方包来“解决”任务,这会扩大攻击面和维护负担。
防护措施:
- 固定版本并提交锁文件
- 限制注册表(或在内部做镜像)
- 要求每个新依赖在 PR 中有简短说明
- 在 CI 中加入 SCA 与密钥扫描,并明确哪些问题会阻止合并
审查 lockfile 的 diff 以发现风险的传递依赖。
我们应如何为 AI 生成代码设定性能期望?
用可测量的目标来定义“优秀”:
- p95/p99 延迟(关键端点)
- 在预期峰值下的吞吐量
- CPU/内存/磁盘/网络的资源使用情况
- 每 1,000 个请求或每个活跃用户的成本
然后在优化前做剖析——避免那种无法用前后数据验证效果的改动。
哪些实用的性能守护措施能防止“能跑但很慢”的代码上线?
使用防护措施避免常见回归:
- 为外部调用设置超时、有限重试和带抖动的退避
- 避免在异步处理链中阻塞操作
- 要求集合端点支持分页/限制
- 只有在有明确失效/失效更新策略(TTL、事件或版本键)时才使用缓存
- 在 CI 中为热点路径加入小规模性能检查(延迟/查询计数阈值)
我们应在 AI 生成的处理器和作业中验证哪些可靠性行为?
可靠性意味着在重试、超时、部分故障和真实输入下保持正确。
关键检查:
- 幂等性:稳定的 key + 持久化的“已处理”记录,适用于支付/Webhook/任务
- 一致性:必要时使用数据库事务;明确写入→发布的顺序(可考虑 outbox)
- 部分失败:处理“DB 成功但发布失败”或“超时但远端已成功”的情况
优先使用有界重试和明确的失败模式,而不是无限重试循环。