重试退避
重试退避
重试策略概览
重试机制应对瞬时故障,通过指数退避避免重试风暴,配合幂等设计保证多次调用结果一致。
指数退避示例:
第1次重试: 1s
第2次重试: 2s
第3次重试: 4s
第4次重试: 8s
第5次重试: 16s(达到最大延迟)
指数退避实现
指数退避将重试间隔指数级增长,避免大量重试同时涌入导致系统雪崩。
public class ExponentialBackoff {
private final long initialDelay;
private final long maxDelay;
private final double multiplier;
public ExponentialBackoff(long initialDelay, long maxDelay, double multiplier) {
this.initialDelay = initialDelay;
this.maxDelay = maxDelay;
this.multiplier = multiplier;
}
public <T> T executeWithRetry(Supplier<T> action) {
long delay = initialDelay;
int attempt = 0;
while (true) {
try {
return action.get();
} catch (Exception e) {
attempt++;
if (attempt >= 5) throw new RuntimeException("Max retries exceeded", e);
sleep(delay + ThreadLocalRandom.current().nextLong(delay / 2));
delay = Math.min((long) (delay * multiplier), maxDelay);
}
}
}
}
幂等设计
幂等保证多次相同请求产生相同结果,是重试机制的前提条件。
@RestController
public class OrderController {
@PostMapping("/orders")
public Order createOrder(@RequestHeader("Idempotency-Key") String key,
@RequestBody OrderRequest request) {
// 幂等键检查
if (idempotencyStore.exists(key)) {
return idempotencyStore.get(key);
}
Order order = orderService.create(request);
idempotencyStore.save(key, order, Duration.ofHours(24));
return order;
}
}
重试与退避配置
// Spring Retry配置
@Configuration
@EnableRetry
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
return RetryTemplate.builder()
.maxAttempts(3)
.exponentialBackoff(1000, 2, 10000)
.retryOn(HttpServerErrorException.class)
.build();
}
}
// 使用示例
@Retryable(
value = {HttpServerErrorException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000, multiplier = 2)
)
public User getUser(String id) {
return restTemplate.getForObject("http://user-service/users/" + id, User.class);
}
重试注意事项
| 要点 | 说明 |
|---|---|
| 幂等前提 | 非幂等操作不可重试 |
| 超时设置 | 重试总时间不超过业务超时 |
| 退避策略 | 指数退避+随机抖动 |
| 降级兜底 | 重试耗尽后触发降级 |