防重核心是服务端生成唯一请求标识并用Redis原子命令校验:基于请求体哈希+时间戳+随机数生成ID,通过SET NX EX实现原子存取,过期设2–5秒,配合Gin中间件封装,兼顾幂等性与客户端提示。
核心思路是:为每次请求生成唯一标识(如基于参数+时间戳+随机数的签名),在接口入口处用 Redis 缓存做“请求指纹”校验,已存在则拒绝处理,否则写入缓存并放行。关键在于标识的唯一性、缓存的原子性、以及过期时间的合理设置。
不依赖客户端传参(易伪造),推荐服务端生成或组合可信字段:
userID:orderID:timestamp 再哈希,天然绑定上下文,防跨用户重放用 SET key value EX seconds NX 命令实现“设值并校验是否新增成功”,单命令保证原子性:
OK → 首次请求,正常执行后续逻辑(nil) → 已存在,直接返回 400 Bad Request 或自定义错误码(如 err: duplicate_request)封装成可复用中间件,自动提取 Body、计算指纹、调用 Redis 校验:
c.Request.Body 读取一次后需用 gin.BindJSON 或 ioutil.ReadAll 重置,避免 Body 被消耗导致下游解析失败真实场景中
还需考虑:
user_id+order_no)或状态机校验(如“待支付”才允许创建)DEL,但要加锁防竞态基本上就这些。不复杂但容易忽略细节,比如 Body 读取顺序、Redis 命令原子性、过期时间粒度——踩过坑才明白为什么有些“防重”上线后还是有重复数据。