负载均衡下请求重试必须与幂等性绑定,否则易致重复扣款、数据错乱;需按操作类型区分是否允许重试,用clienttoken或业务唯一id实现服务端幂等控制,并在客户端和服务端协同校验参数一致性。

负载均衡下的请求重试,不能简单理解为“失败了再发一次”。真正落地高可用环境时,重试必须和幂等性绑定——没有幂等保障的重试,轻则重复扣款、多建订单,重则引发数据错乱甚至资损。
重试前先确认操作是否幂等
不是所有接口都适合开启重试。关键看业务逻辑是否满足“多次执行 = 一次执行”的效果:
-
适合重试的幂等操作:查询类(
GET /user/123)、状态覆盖类(PATCH /order/456 {status: "shipped"})、带唯一约束的插入(如用订单号做数据库唯一索引) -
禁止重试的非幂等操作:支付扣款(
POST /pay)、库存预减(POST /stock/decrease)、消息发送(可能重复投递) - 若不确定,优先按非幂等处理;宁可人工补偿,也不盲目自动重试
用 ClientToken 或业务唯一ID 实现服务端幂等控制
客户端每次发起请求时,必须携带一个全局唯一、一次一换的标识符,服务端据此判重:
- 推荐使用标准 ClientToken:由客户端生成 UUID(如
123e4567-e89b-12d3-a456-426655440001),长度≤64 ASCII 字符,区分大小写 - 也可复用业务已有唯一字段,如订单号、交易流水号——前提是该字段在请求发起时已确定且不依赖服务端生成
- 服务端收到请求后,先查缓存(Redis)或数据库中是否存在该 token 对应的处理结果;存在则直接返回,不走后续业务逻辑
负载均衡器侧的重试配置要克制且精准
Nginx、Spring Cloud LoadBalancer、Dubbo 等组件支持自动重试,但必须限制范围和条件:
- 只对特定 HTTP 状态码重试:如
502/503/504(网关错误、服务不可用、网关超时),不重试 4xx 错误(多数是客户端问题) - 设置合理重试次数:通常 最多额外重试 1~2 次(即总尝试 2~3 次),避免放大故障或引发重试风暴
- 启用退避策略:第二次重试前加短延时(如 100ms),缓解下游压力;Nginx 可用
proxy_next_upstream_tries和proxy_next_upstream_timeout - 注意 HTTP 方法限制:默认仅对幂等方法(GET、HEAD、PUT、DELETE)开启重试;POST 等非幂等方法需显式开启并确保已做幂等防护
客户端与服务端协同验证幂等性边界
单靠一方无法兜底,需两端配合守住一致性:
- 客户端在重试时,必须保证 除时间戳、签名参数外,其余入参完全一致(如 ClientToken、body、query 都不能变)
- 服务端校验时,若发现 token 已存在但新请求参数有差异(比如金额变了),应拒绝并返回
IdempotentParameterMismatch类错误 - 建议在日志中统一打印 ClientToken,便于全链路追踪和问题定位
- 测试阶段必须覆盖“网络超时→客户端重发→服务端幂等拦截”完整路径,不能只测成功流程











