agent操作中的幂等性设计方案
幂等性是指同一个操作无论执行一次还是多次最终产生的业务结果是一致的。对于涉及 AI Agent 这种长链路、高成本的场景如果前端抖动重试或网关超时重发导致系统重复触发了 Agent 生成、重复扣费或覆盖了正在生成的任务那将是灾难性的。在我们的系统中一个“论文写作任务”包含研究、提纲、章节生成等多个阶段。我们需要解决三个具体的并发问题重复触发用户手抖点了两次“生成章节”或者网络超时导致请求重试。我们不允许为同一个请求创建两个TaskRun任务运行记录。状态冲突同一个任务不能同时有两个 Agent 在跑比如一个在写引言一个在写实验否则状态机容易乱。结果重复Agent 跑完后回调保存结果时不能因为回调重试而生成两份章节版本。第一道防线幂等键与请求摘要首先我们在应用层定义了幂等键。 在这个项目中我们的幂等键组合是taskId任务IDaction动作如 GENERATE_SECTIONrequestId请求唯一标识。但这还不够。如果攻击者拿着一个旧的requestId但篡改了请求内容比如把“写引言”改成“写实验”发过来系统如果只认 ID就会错误地返回旧结果。因此我们引入了请求摘要。// 计算本次请求的语义摘要 String requestHash WritingHashes.sha256(String.join(\n, taskId.toString(), outline.id().toString(), section.sectionKey(), instruction, contextBuilder.budgetFingerprint(), citation-schema1));我们在处理请求时会计算当前请求内容的 Hash 值。如果数据库里已经存在这个requestId我们会比对 HashHash 一致说明是真正的重复请求直接返回已有结果。Hash 不一致说明是幂等键冲突ID 重用了但内容变了抛出IDEMPOTENCY_CONFLICT异常拒绝执行。第二道防线JVM 锁与事务内的“先查后插”有了幂等键最直观的做法是“先查数据库有没有没有就插”。但在高并发下两个请求可能同时查不到然后双双插入成功。为了解决这个问题我们在代码入口处加了taskId 级别的 JVM 锁Object lock taskLocks.computeIfAbsent(taskId, ignored - new Object()); synchronized (lock) { return transactions.required(() - { // 1. 查幂等记录 TaskRun existing runRepository.findByTaskIdActionAndRequestId(...); if (existing ! null) { requireMatchingHash(existing, requestHash); // 校验摘要 return SectionAcceptance.idempotent(existing); } // 2. 检查是否有正在运行的任务 if (runRepository.existsRunningByTaskId(taskId)) { throw new WritingConflictException(TASK_RUN_CONFLICT, ...); } ​ // 3. 创建并启动新任务 TaskRun run TaskRun.create(...); run.start(); runRepository.save(run); return SectionAcceptance.started(run, ...); }); }锁的粒度我们锁的是taskId而不是全局锁。这意味着不同的论文任务可以并行处理互不干扰保证了吞吐量。顺序很重要我们是先获取锁再在事务里查库。这保证了在单机环境下同一时刻只有一个线程能执行“检查创建”的逻辑彻底杜绝了并发竞争。第三道防线数据库唯一约束终极兜底JVM 锁只能解决单实例的问题。如果我们的服务部署了多个实例集群模式JVM 锁就失效了。这时候数据库约束就是最后一道防线。我们设计了两张“王牌”索引1. 幂等唯一约束CONSTRAINT uq_writing_run_action_request UNIQUE (task_id, action, request_id)这就是幂等键在数据库层面的物理落实。它保证了对于同一个任务、同一个动作、同一个请求 ID数据库里绝对只能有一条记录。即使两个实例同时越过应用层检查数据库也会拦截住第二个插入请求。2. 运行状态互斥约束CREATE UNIQUE INDEX uq_writing_task_running_run ON writing_task_runs(task_id) WHERE status RUNNING;这是一个部分唯一索引Partial Unique Index。它非常巧妙它只限制statusRUNNING的记录唯一。当一个任务正在运行RUNNING时第二个请求想插入 RUNNING 状态会被数据库拒绝。当任务结束变成 SUCCESS/FAIL后这个限制就解除了允许开启新的任务。 这就完美解决了“同一任务同一时间只能有一个 Agent 在跑”的问题而不需要额外的状态机锁。第四道防线冲突后的“优雅回读”虽然数据库约束保证了数据不脏但如果直接抛出DataIntegrityViolationException唯一键冲突异常给前端体验并不好。在文档组装接口中我们实现了更优雅的处理捕获冲突回读胜者。try { // 尝试创建 DocumentVersion result transactions.required(() - commit(...)); return response(result); } catch (DataIntegrityViolationException conflict) { // 冲突了没关系看看是谁赢了 DocumentVersion recovered transactions.required(() - recoverUniqueConflict(taskId, requestId, requestHash, ...) ); if (recovered ! null) { return response(recovered); // 返回已有的结果 } throw conflict; }这种“先尝试插入失败则回读”的模式在多实例并发下能提供类似分布式锁的体验但实现成本更低。注目前我们的研究、提纲和章节生成接口暂时只做到了抛出异常后续可以统一升级为这种回读模式。补充防止结果重复生成除了防止“任务重复创建”我们还要防止“结果重复生成”。 Agent 运行结束后会回调保存章节版本。为了防止回调被重复消费我们在章节版本表设计了generated_by_run_id UUID NOT NULL UNIQUE这保证了一个TaskRun只能对应一个章节版本。即使回调逻辑因为网络原因被触发了两次第二次写入也会因为唯一键冲突而失败从而保护了业务数据的纯净。

相关新闻

yoinks命令行参数与用法完整清单:--help背后的所有选项

yoinks命令行参数与用法完整清单:--help背后的所有选项

yoinks命令行参数与用法完整清单:--help背后的所有选项 【免费下载链接】yoinks yoink any video from your terminal. no shady ads. 项目地址: https://gitcode.com/GitHub_Trending/yo/yoinks yoinks 是一款命令行视频下载工具:在终端粘贴 You…

2026/10/5 9:41:37 阅读更多 →
博图的离散量报警

博图的离散量报警

我做的是根据factio这三个伸出异常和挡板异常的报警信息,看的是老A的视频,大家感兴趣可以去看1.创建报警db块,取消优化块的访问,因为离散量报警好像需要地址寻址,所以我做的int类型,bool类型触摸屏无法找到…

2026/10/5 9:41:37 阅读更多 →
DeepSeek+Kimi双AI协作:一小时生成23页PPT的实战指南

DeepSeek+Kimi双AI协作:一小时生成23页PPT的实战指南

简介:数字化工作环境中制作专业演示文稿常需兼顾内容质量与效率,这份23页PPT报告正是围绕DeepSeek与Kimi协同完成PPT制作的完整方法讲解,适合职场人士、学术研究者及需要高频产出汇报材料的初学者。资源包共1个pptx文件,大小36.97…

2026/10/5 9:40:36 阅读更多 →

最新新闻

PHP-FPM vs 传统模式:性能与安全的终极对决

PHP-FPM vs 传统模式:性能与安全的终极对决

现代生产那环境需要选取使用php -fpm而并非其他的, 这是由于它能够支持动态方面能伸缩调整、实现平滑地重启以及具备细粒度的方面资源控制;并且还需要去匹配Event MPM与之相关的, 要启用起来并且对配置进行优化, 同时还要禁用掉.解析, 只有这样才能够提升PHP执行的效…

2026/10/5 10:20:52 阅读更多 →
详细剖析ethercat中容易混淆的三种抖动

详细剖析ethercat中容易混淆的三种抖动

一、三种抖动,三件不同的事 1**. 周期抖动(Cycle Jitter)—— 主站的心跳稳不稳** 主站每隔固定时间发一帧过程数据,比如 1ms。实际发送间隔可能是 999.4μs、1002.8μs、1000.1μs……这些值与 1000μs 的偏差就是周期抖动。 它只…

2026/10/5 10:20:52 阅读更多 →
EtherCAT 完整数据帧结构剖析(按字节)

EtherCAT 完整数据帧结构剖析(按字节)

2026/10/5 10:20:52 阅读更多 →
最弱模型竟成顶级AI解码器

最弱模型竟成顶级AI解码器

AI蒸馏,实锤了?2026年,硅谷最敏感的一桩悬案,就是AI蒸馏。每当, 一款新模型, 突然变强, 跑分, 直追GPT, 回答, 又带着的味道, 同一个问题, 就会开始, 在业内游荡。所有人都在怀疑,却没有人能把证据拍在桌上。直到今天&…

2026/10/5 10:20:52 阅读更多 →
中国研究生数学建模竞赛(华为杯)学习笔记——TOPSIS评价法

中国研究生数学建模竞赛(华为杯)学习笔记——TOPSIS评价法

文章目录TOPSIS简介方法和原理数学定义数学语言描述现实案例正负理想解定义实例量纲TOPSIS法的算法步骤1.用向量规范化的方法求得规范决策矩阵2.构成加权规范阵3.确定正负理想解的距离4.计算各方案到正理想解与负理想解的距离5.计算各方案的综合评价指数6.排列方案的优劣次序实…

2026/10/5 10:20:52 阅读更多 →
鸿蒙开发第2篇__装饰器

鸿蒙开发第2篇__装饰器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 10:19:52 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →