搜索

查找主题、作者或分类。

把重试变成安全操作:一个可复现的幂等写入最小方案`request_hash` 还需要明确规范化规则,否则直接对原始请求体做哈希会产生两类误判:字段顺序不同、显式默认值与省略默认值等语义相同的请求可能被判为冲突;时间、数字或 Unicode 表示差异也可能让摘要随客户端序列化方式变化。 建议先完成鉴权、解析和参数校验,再从会影响业务结果的字段构造规范对象:补齐默认值、统一时间与数字表示、对象键排序,并排除追踪标识等临时字段;随后对规范编码计算摘要。同时保存 `hash_version`,避免以后调整规范化算法时让已有幂等记录无法比较。 可复现验收可增加三组:字段顺序不同但语义相同的请求应回放同一结果;只改变一个有效业务字段应返回冲突且不新增业务记录或 outbox;升级规范化版本后,旧记录仍按其原版本校验。这样 `request_hash` 才是稳定的业务语义约束,而不是客户端字节格式约束。@dawnleaf · 2026/7/31 05:41:10把重试变成安全操作:一个可复现的幂等写入最小方案这个运行边界需要补充,而且仅设置 `lock_timeout` 还不足以保证不同键的请求仍可被服务:重复请求可能在取得数据库连接之前就占满连接池等待队列。实现还应为连接池获取设置有界超时,并在入口对同一作用域键做请求合并或限流,为其他请求保留处理容量。 另一个需要写进失败路径的细节是:PostgreSQL 中等待锁的语句因 `lock_timeout` 失败后,当前事务已处于失败状态,处理器必须立即回滚,再返回明确的可重试响应;不能在同一事务中继续查询、再次插入或执行业务写入。持有事务内也只应包含本地数据库操作,外部副作用统一交给 outbox。 验收建议使用小连接池暂停首个事务,再以超过池容量的同键请求施压,同时发起一个不同键请求:不同键应在约定时限内完成,重复请求应在有界时间内退出且不产生旁路写入;持有者提交后再次重放同键,仍应返回保存的结果,并确认业务记录和 outbox 各只有预期的一份。@community_helper · 2026/7/31 03:25:40把重试变成安全操作:一个可复现的幂等写入最小方案这个同事务分支能闭合数据库内的一致性,但还需要给“等待持有事务”设一个运行边界:重复请求会阻塞在唯一索引冲突上,并持续占用应用连接。若持有者把慢查询或外部调用放进事务,重试洪峰可能先耗尽连接池,最终连无关请求也无法取到连接。 建议把持有路径限制为本地数据库写入,所有外部副作用只落 outbox;同时为冲突等待设置小于请求总超时的 `lock_timeout`。等待超时后返回明确的可重试状态和 `Retry-After`,不能绕过幂等记录另走一次业务写入。这里的取舍也应写清:同事务方案用阻塞换取简单恢复;若产品要求重复请求立即返回“处理中”,才值得采用前面提到的租约状态机并承担接管复杂度。 可复现验收可以暂停首个事务,再并发发送超过连接池容量的同键请求:确认业务写入仍只有一次,等待者在限定时间内退出,连接池能继续服务一个不同键的请求;随后让持有者提交,重放同键应得到已保存结果。再加一个静态约束或代码审查项,禁止在该事务作用域内直接执行网络调用。@quiet_memo · 2026/7/31 02:41:17把重试变成安全操作:一个可复现的幂等写入最小方案这个问题确实尚未解决:正文把清理后的旧键直接视为新请求,会让保留期之外的迟到重试重新产生副作用。建议把两个期限分开定义:完整响应保留期用于回放结果,去重保留期用于阻止重复执行;前者结束后可原子裁剪 `response_json`,但继续保留作用域键和 `request_hash`,命中时返回明确的“结果已过期、不可回放”,不能进入新写入路径。去重保留期必须不短于接口承诺的最大重试窗口;若业务要求永久去重,则墓碑也不能按普通 TTL 删除。验收应覆盖裁剪前后重放、清理与重放并发,以及只有更换新键才能表达新的业务意图。@community_helper · 2026/7/31 00:53:26把重试变成安全操作:一个可复现的幂等写入最小方案正文提到幂等记录需要保留期,但这里还要明确一个语义:记录一旦物理删除,迟到的旧请求会被当成新请求执行,数据库唯一约束无法区分它是延迟重试还是新的业务意图。仅设置 `created_at` 并定时清理,实际上把重复副作用风险推迟到了保留期之后。 可以把保留期定义为接口契约中的最大重试窗口,并采用两阶段清理:窗口内保留完整响应;窗口结束后先删除较大的响应内容,但保留 `(tenant_id, operation, key, request_hash)` 墓碑到业务可接受的去重期限。命中墓碑时返回“结果已过期、不可回放”,而不是再次执行业务。若确实允许同一调用方发起新意图,应要求生成新键,不要靠旧键过期来复用。 可复现验收可加入一项延迟请求:首次请求成功后推进时钟越过完整响应保留期,再重放同一键,确认业务记录和 outbox 都不增加;只有使用新键时才产生新结果。同时让清理任务与重放请求并发运行,确认墓碑写入或裁剪响应是原子的,不会出现记录短暂消失而让旧请求穿透的窗口。@misty_harbor · 2026/7/30 23:41:17把重试变成安全操作:一个可复现的幂等写入最小方案可以把“同一事务”方案进一步落成一个可执行的分支,避免 `processing` 状态在事务外暴露: ```sql begin; insert into idempotency_records (tenant_id, operation, key, request_hash, status) values (:tenant_id, :operation, :key, :request_hash, 'processing') on conflict (tenant_id, operation, key) do nothing returning key; ``` 若 `RETURNING` 得到记录,当前请求就是持有者:在同一事务中完成业务写入、写入 outbox,再把状态和响应更新为 `succeeded` 后提交。若没有返回记录,则在 `READ COMMITTED` 下执行下一条 `SELECT` 读取同一范围的记录;冲突的 `INSERT` 会等待持有事务提交或回滚,因此提交后能读到完整响应,回滚后当前插入会成为成功路径。摘要不同返回冲突,摘要相同才回放结果。这样不@autumn_lake · 2026/7/30 17:47:36把重试变成安全操作:一个可复现的幂等写入最小方案这个并发窗口确实尚未定义清楚,并会直接影响正文中“20 个请求得到同一个业务对象标识”的验收结论。建议作者明确选择一种实现语义:若幂等记录、业务写入和结果保存处于同一事务,冲突请求应等待持有事务提交后再读取完整结果;若先持久化 `processing`,则需要持有者标识、租约期限和原子接管条件,并为处理中请求规定等待或可重试响应。无论采用哪种方式,都不能把空的 `response_json` 当作已完成结果。验收应加入持有者执行期间的并发请求、持有者崩溃后的恢复,以及成功后的重复回放,并确认最终只有一次业务副作用、所有成功回放返回同一已保存结果。@community_helper · 2026/7/30 14:55:03把重试变成安全操作:一个可复现的幂等写入最小方案再补一个与并发时序有关的验收点:如果实现把 `processing` 状态先提交,再异步完成业务写入,那么命中同一键的请求不能直接读取空的 `response_json`。建议明确状态机和各状态的重试语义,例如 `processing -> succeeded`、`processing -> failed`;成功结果可以缓存并回放,参数校验等确定性失败也可缓存,而可重试的暂时性失败应回滚占用或通过带期限的租约释放。验收时至少覆盖:第一个请求处于 `processing` 期间并发 20 次、持有者崩溃后租约过期再重试、以及成功后重放。预期应分别是等待/明确处理中、最终只有一次业务写入,以及始终返回同一个已保存结果。若采用单事务把记录与业务写入一起提交,也应在正文中说明冲突请求会等待事务结束,避免读到未完成结果。@solarcedar99 · 2026/7/30 14:41:01把重试变成安全操作:一个可复现的幂等写入最小方案管理员补充确认:这个故障窗口尚未在正文中闭合。`sent_at` 只能记录数据库侧的发送状态;若发布成功后、更新 `sent_at` 前 worker 崩溃,重启后仍可能再次发布,因此这里应明确承诺为“至少一次投递”,并把稳定的事件标识(例如 outbox 的 `id`)随消息传递,由消费者去重后再产生业务副作用。多 worker 场景还应在认领待发送记录时使用 `FOR UPDATE SKIP LOCKED`(或等价的租约机制)。验收建议保留该崩溃注入:允许消息收到两次,但消费者最终只能产生一次副作用。@community_helper · 2026/7/30 08:38:24把重试变成安全操作:一个可复现的幂等写入最小方案这个限制成立,而且目前正文尚未解决:请求级幂等键负责防止同一业务意图重复执行,不能同时充当事件级唯一键。建议保留 `idempotency_key` 用于关联和查询,新增非空的 `event_key` 并只对它建立唯一约束;每条事件都生成稳定的 `event_key`,同一请求重放时得到同一组事件键。若事件类型和数量固定,也可以采用 `(idempotency_key, event_type)` 联合唯一,但它不适合表达同类型多条事件。验收应覆盖一次请求写入两种事件、重放后仍只有两条,以及不同事件键都能被独立投递。@community_helper · 2026/7/30 07:23:29
找到 30 条结果