PHP接口防重推荐实现
防重实现方法
使用唯一请求标识符(UUID或业务ID)作为防重依据,客户端每次请求生成唯一标识,服务端校验该标识是否已处理过。适合短时间内的重复请求拦截。
// 客户端生成唯一标识
$requestId = uniqid('req_', true);
// 服务端校验逻辑
$cacheKey = 'api_request:'.$requestId;
if ($redis->exists($cacheKey)) {
throw new Exception('重复请求');
}
$redis->setex($cacheKey, 60, 1);
时间戳+签名验证
客户端将当前时间戳与请求参数拼接后生成签名,服务端验证时间戳有效性(如5分钟内)及签名是否匹配。超过时间窗口的请求自动失效。

// 客户端生成签名
$timestamp = time();
$sign = md5($timestamp . $params . $secretKey);
// 服务端验证
if (abs(time() - $timestamp) > 300) {
throw new Exception('请求已过期');
}
if ($sign !== md5($timestamp . $params . $secretKey)) {
throw new Exception('签名错误');
}
幂等性设计
对于写操作接口,采用天然幂等设计。如订单创建使用唯一订单号,重复提交返回已存在的订单数据。数据库层面通过唯一索引约束防止重复数据。

ALTER TABLE orders ADD UNIQUE INDEX uk_order_no (order_no);
令牌桶限流
使用Redis实现令牌桶算法,控制单位时间内接口调用次数。适用于防止高频重复调用场景。
$rateLimiter = new TokenBucket(
redis: $redis,
key: 'api_rate_limit:user_123',
capacity: 10,
tokens: 10,
fillRate: 1
);
if (!$rateLimiter->consume(1)) {
throw new Exception('请求过于频繁');
}
数据库乐观锁
更新操作时通过版本号控制,确保数据变更的原子性。适合防止并发重复提交导致的数据不一致。
// 更新时带版本条件
$affected = $db->execute(
'UPDATE products SET stock = stock - 1, version = version + 1
WHERE id = ? AND version = ?',
[$productId, $currentVersion]
);
if ($affected === 0) {
throw new Exception('库存更新冲突');
}






