指数退避算法详解

2022-05-31JAVA语音

一、什么是指数退避算法

指数退避算法是适用于网络应用的标准错误处理策略,使用这种策略时,客户端会定期重试失败的请求,并不断增加各次请求之间的延迟时间。

二、示例算法

指数退避算法以指数方式重试请求(不断增加各次重试之间的等待时间,直到达到最大退避时间)。示例如下:

(1)客户端发出请求。
(2)如果请求失败,请等待 1 + random_number_milliseconds 秒后再重试请求。
(3)如果请求失败,请等待 2 + random_number_milliseconds 秒后再重试请求。
(4)如果请求失败,请等待 4 + random_number_milliseconds 秒后再重试请求。
(5)依此类推,等待时间上限为 maximum_backoff。

等待时间达到上限后,您可以继续等待并重试,直到达到重试次数上限(但接下来的重试操作不会增加各次重试之间的等待时间)。

其中:

a.等待时间为 min(((2^n)+random_number_milliseconds), maximum_backoff),其中,n 会在每次迭代(请求)后增加 1。

b.random_number_milliseconds 是小于或等于 1000 的毫秒数(随机值)。这有助于避免出现以下情况:许多客户端在某些情况下全部同步进行处理并同时执行重试操作,导致同步发送每一波请求。每次重试请求后,系统都应重新计算 random_number_milliseconds 值。

c.maximum_backoff 通常为 32 或 64 秒。哪个值更为适当,这取决于用例。

d.达到 maximum_backoff 时间后,您可以继续重试。 此后执行的重试不需要继续增加退避时间。

例如,如果客户端使用的 maximum_backoff 时间为 64 秒,则在达到此值后,客户端可以每 64 秒重试一次。在某个时刻,应阻止客户端无限重试。

三、Spring retry退避算法

1、maven依赖

<dependency>
  <groupId>org.springframework.retry</groupId>
  <artifactId>spring-retry</artifactId>
  <version>1.2.5.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aspects</artifactId>
  <version>5.2.8.RELEASE</version>
</dependency>

2、java代码

@Service
public class OrderService {
  private Logger logger = LoggerFactory.getLogger(this.getClass());
  private AtomicInteger loop = new AtomicInteger(1);
  private Instant instantBefore;
  @Retryable(
      value = RuntimeException.class , //抛出该异常时,进行重试
      maxAttempts=12, // 最大重试次数,超过直接抛出异常
      backoff =
      @Backoff(
          delay=500, //初始delay时间
          multiplier = 2, // 设置为2时,可以理解为
          maxDelay=10000, // min(delay * multiplier^(attempt - 1), maxDelay)
          random = false //是否使用随机数
      )
  )
  public void readOrder(String orderId){
    Instant now = Instant.now();
    long gap = instantBefore == null ? 0 : Duration.between(instantBefore, now).toMillis();
    logger.info("{} --- time-gap :{}",loop.getAndIncrement(),gap);
    instantBefore = now;
    if( 1 < 2) throw new RuntimeException(); // 抛出异常,进行重试
  }
}

上述算法可以描述为: min(delay * multiplier^(attempt - 1), maxDelay),

当multiplier=2 && random=true,可以近似理解为指数退避算法。

执行结果如下:

版权声明:本文为老张的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://www.webppp.com/view/zhi_shu_tui_bi_suan_fa.html