服务端与数据 / 进阶
接口幂等:网络重试不应该创建两笔订单
客户端超时后重试是正常行为。对支付、下单等写接口,引入幂等键并在数据库事务中认领请求,才能避免重复副作用。
超时不代表服务端没有执行
客户端在 2 秒后超时,但服务端可能已经提交订单,只是响应丢失。此时再次 POST 会生成第二笔订单。幂等的目标不是禁止重试,而是让同一个业务意图的多次提交得到同一个结果。
保存请求指纹和最终响应
同一个用户和 key 只能插入一次。request_hash 用于阻止客户端误用同一个 key 提交不同参数;完成后保存状态码和响应体,后续重试直接返回快照。
EXAMPLE / 02Idempotency
CREATE TABLE idempotency_keys (
user_id bigint NOT NULL,
key text NOT NULL,
request_hash text NOT NULL,
status text NOT NULL CHECK (status IN ('processing', 'completed')),
response_status int,
response_body jsonb,
expires_at timestamptz NOT NULL,
PRIMARY KEY (user_id, key)
);在事务里认领请求
读取 Idempotency-Key,并校验格式和长度;在事务中插入 processing 记录;唯一冲突时读取已有记录;如果 request_hash 不同,返回 409;如果已 completed,原样返回响应快照;只有认领成功的请求执行业务写入,并把幂等记录更新为 completed。
锁过期、进程崩溃或 Redis 故障都可能让业务数据和幂等状态分离。最终防线应是与业务写入同库的唯一约束和事务。