PHP接口防重推荐实现
使用唯一请求标识符
为每个请求生成唯一标识符(如UUID),服务端校验该标识符是否已处理过。客户端在请求头或参数中携带该标识符,服务端通过缓存记录已处理的标识符。
// 生成唯一请求ID
$requestId = uniqid('req_', true);
// 存储到Redis并设置过期时间
$redis->setex("req:{$requestId}", 3600, 1);
时间戳+随机数签名
客户端将当前时间戳与随机数拼接后生成签名,服务端验证时间戳的有效期(如5分钟内)和签名唯一性。超过时间窗口的请求自动失效,重复签名直接拒绝。
$timestamp = time();
$nonce = mt_rand(1000, 9999);
$signature = md5("{$timestamp}{$nonce}{$secretKey}");
幂等性设计
对写操作接口采用幂等设计,通过业务唯一键(如订单号)保证重复请求只生效一次。数据库使用唯一索引或乐观锁控制并发重复提交。
UPDATE orders SET status = 'paid'
WHERE order_no = '20230801123456'
AND status = 'unpaid';
请求参数指纹
提取关键参数生成指纹(如MD5哈希),服务端缓存指纹与处理结果的映射。相同指纹请求直接返回缓存结果,避免重复处理。
$params = ['user_id'=>123, 'product_id'=>456];
ksort($params);
$fingerprint = md5(http_build_query($params));
分布式锁控制
使用Redis或Zookeeper实现分布式锁,在关键业务操作前获取锁。锁持有期间其他重复请求会被阻塞或快速失败,确保操作的原子性。
$lockKey = 'order_create_123';
if ($redis->set($lockKey, 1, ['NX', 'EX'=>10])) {
// 处理业务
$redis->del($lockKey);
}
客户端防抖机制
前端通过JavaScript控制按钮提交状态,提交后禁用按钮或显示加载状态。配合服务端验证可有效减少意外重复提交。
document.getElementById('submitBtn').disabled = true;
fetch('/api/submit', { method: 'POST' });
数据库乐观锁
通过版本号字段实现乐观锁,更新时校验版本号匹配才执行操作。适用于高并发场景下的数据一致性保护。
UPDATE products SET stock = stock - 1, version = version + 1
WHERE product_id = 100 AND version = 5;
每种方案适用于不同场景,可根据实际需求组合使用。时间戳签名适合普通API,幂等性设计适合交易系统,分布式锁适合秒杀等高并发场景。







