前言:
前时间出了一个小问题,下游的服务时不时的阻塞,我这边为了确保数据一致性,不断的重试请求,这样的后果自然是雪上加霜。当然,下游处理的有待提高,但我们是否有更好的办法来优化重试? 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/