golang backoff重试指数退避算法

前言:

前时间出了一个小问题,下游的服务时不时的阻塞,我这边为了确保数据一致性,不断的重试请求,这样的后果自然是雪上加霜。当然,下游处理的有待提高,但我们是否有更好的办法来优化重试? backoff 指数退避算法就是干这事的.

该文章后续仍在不断的更新修改中, 请移步到原文地址 http://xiaorui.cc/?p=5836

backoff 退避算法

什么是退避算法?通常我们的某服务发生故障时,我们会固定间隔时间来重试一次?但这样会带来一些问题,同一时间有很多请求在重试可能会造成无意义的请求。

指数退避算法会利用抖动(随机延迟)来防止连续的冲突。 效果如下,每次间隔的时间都是指数上升,另外加了少许的随机。

等待时间:101 ms
等待时间:208 ms
等待时间:413 ms
等待时间:821 ms
等待时间:1602 ms
等待时间:3203 ms

我这边封装了golang backoff的指数退避库,有兴趣的可以看看代码https://github.com/rfyiamcool/backoff

backoff的代码实现简单,他的使用方法也简单,给出一个例子。

b := NewBackOff(
    WithMinDelay(100*time.Millisecond),
    WithMaxDelay(10*time.Second),
    WithFactor(2),
)

equals(t, b.Duration(), 100*time.Millisecond)
equals(t, b.Duration(), 200*time.Millisecond)
equals(t, b.Duration(), 400*time.Millisecond)
for index := 0; index < 100; index++ {
    b.Duration()
}

// is max
equals(t, b.Duration(), 10*time.Second)
b.Reset()
equals(t, b.Duration(), 100*time.Millisecond)

如果要实现少许的随机延迟时间,需要开启jitter参数

b := NewBackOff(
    WithMinDelay(100*time.Millisecond),
    WithMaxDelay(10*time.Second),
    WithFactor(2),
    WithJitterFlag(true),
)

equals(t, b.Duration(), 100*time.Millisecond)
between(t, b.Duration(), 100*time.Millisecond, 200*time.Millisecond)
between(t, b.Duration(), 100*time.Millisecond, 400*time.Millisecond)
b.Reset()
equals(t, b.Duration(), 100*time.Millisecond)

总结:

 

来源:http://xiaorui.cc/2019/04/23/golang-backoff%E9%87%8D%E8%AF%95%E6%8C%87%E6%95%B0%E9%80%80%E9%81%BF%E7%AE%97%E6%B3%95/

posted @ 2019-12-30 18:10  gao88  阅读(2621)  评论(0编辑  收藏  举报