1. 幂等键(Idempotency Key)模式中接口层用请求唯一标识实现幂等的通用框架?
请解释幂等键(Idempotency Key)模式,说明接口层如何用请求唯一标识实现幂等,并给出一个通用框架的设计思路?
- 幂等键的生成与传递(客户端生成 UUID)
- 服务端按幂等键去重与结果缓存
- 并发冲突与结果一致性
幂等键模式:客户端在发起写操作时生成一个唯一的请求标识(Idempotency Key,通常是 UUID),携带在请求头(如 Idempotency-Key)中。服务端收到请求后,先按该键查缓存/存储:若已处理过则直接返回之前的结果,避免重复执行;若未处理则执行并记录(键 → 结果)。
通用框架设计:
- 生成与传递:客户端为每次业务操作生成唯一键,网络重试时复用同一键。
- 服务端存储:用一个幂等表(idempotency store)记录
(键, 请求哈希, 响应, 状态, 时间),键为主键,带唯一约束。 - 并发处理:同一键并发到达时,用数据库唯一索引/分布式锁保证只有一个请求真正执行,其余等待或返回缓存结果。
- 结果返回:已处理过返回存储的响应,包括状态码与 body,保证客户端重试得到一致结果。
- 清理:幂等记录设置 TTL,防止无限增长。
关键点:幂等键必须由客户端生成并在重试间复用;服务端用"唯一键 + 原子插入"保证幂等;返回缓存结果保证一致性。典型实现如 Stripe 的 Idempotency-Key 头。
幂等键把"请求是否已处理"的判断从业务逻辑剥离到框架层,是防止重复下单/重复扣款等副作用的关键。核心是"唯一约束 + 结果缓存"。
// 幂等键存储(伪代码)
public class IdempotencyService {
void handle(String key, Request req, Supplier<Response> action) {
if (store.get(key) != null) return store.get(key); // 已处理,返回缓存
try {
store.insert(key, "processing"); // 唯一约束,冲突则等待
Response resp = action.get();
store.update(key, "done", resp);
return resp;
} catch (DuplicateKeyException e) {
return store.get(key); // 并发重复,返回结果
}
}
}