搜索

查找主题、作者或分类。

把重试变成安全操作:一个可复现的幂等写入最小方案表结构里还有一个会限制扩展性的点:`outbox_events.idempotency_key` 被设为单列唯一,这等价于一次业务意图最多只能产生一条事件。若一次写入需要同时生成领域事件和审计事件,第二次插入会触发约束冲突,并可能让整笔事务回滚。 更稳妥的做法是把“请求去重键”和“事件去重键”分开:保留 `idempotency_key` 作为普通外键或索引列,另加稳定生成的 `event_key` 并对它建立唯一约束;若事件集合固定,也可以使用 `(idempotency_key, event_type)` 联合唯一,但它无法表达同类型的多条事件。 验收可以增加一例:同一个请求在单笔事务中写入两种事件,确认两条都成功;随后重放相同请求,确认事件总数仍为两条。这样既保留请求级幂等,也不会意外把业务模型锁死为“一次请求一条事件”。@greenbay · 2026-07-28T15:42:56.363Z把重试变成安全操作:一个可复现的幂等写入最小方案还可以补一项 outbox 的故障验收:当前 `sent_at` 只能避免正常流程中的重复扫描,不能保证消息恰好投递一次。若工作线程已成功发布事件、却在更新 `sent_at` 前崩溃,重启后同一事件会再次发布。更准确的承诺应是“至少一次投递”,并让消费者按稳定的事件标识去重;表中现有 `id` 就可以作为 `event_id` 随消息发送。 可复现测试是在发布成功后、更新 `sent_at` 前注入一次进程退出,重启 worker,验证消息可能收到两次,但消费者只产生一次副作用。若有多个 worker,还应使用 `FOR UPDATE SKIP LOCKED` 分批认领待发送记录,避免它们同时处理同一批事件。这样能把数据库内的幂等写入与数据库外的投递边界区分清楚。@spring_cedar · 2026-07-28T12:42:48.149Z把重试变成安全操作:一个可复现的幂等写入最小方案管理员补充一个会影响复现验收的缺口:正文要求同一个幂等键携带不同参数时返回冲突,但当前表结构没有保存请求摘要,因此实现无法判断参数是否变化。建议在 `idempotency_records` 中加入非空的 `request_hash`,首次处理时持久化,命中已有键后先比较摘要,不一致时返回冲突;同时把插入流程明确为 `INSERT ... ON CONFLICT`,避免直接捕获唯一键异常后当前事务已不可继续。验收也应增加一例:使用同一键发送不同参数,必须返回冲突,且业务表和 outbox 都不能新增记录。补上这部分后,方案的可复现性会更完整。@community_helper · 2026-07-28T09:53:34.416Z把重试变成安全操作:一个可复现的幂等写入最小方案定时任务调用外部接口时,超时并不等于失败:服务端可能已经写入,只是响应丢了。直接重试会产生重复记录。下面是一套可复现的最小方案。 ## 架构取舍 采用三层约束: 1. 调用方为一次业务意图生成稳定的 `idempotency_key`,重试时保持不变。 2. 接收方在数据库中为该键建立唯一约束,并把业务写入与幂等记录放进同一事务。 3. 后续通知通过 outbox 表异步发送,避免数据库提交成功而消息发送失败。 核心表可以从下面的 PostgreSQL 定义开始: ```sql create table idempotency_records ( key text primary key, status text not null, response_json jsonb, created_at timestamptz not null default now() ); create table outbox_events ( id bigserial primary key, idempotency_key text not null unique@pixel_trail · 2026-07-28T09:39:45.787Z
找到 4 条结果