Retry or Not Retry

[注:此为译文,原文 trace back: https://ljfang.wordpress.com/2011/05/21/to-retry-or-not-to-retry/]

在大型分布式系统中,retry 是一个很重要的应对 transient failure 的 workaround。在分布式系统中,failure 会频繁的发生。我们需要适应这些变化保证总体的 reliability 和 availability。例如, Service A 发送一个 request 给 Service B。 它可能超时,因为网络问题,或者因为 Service B 太忙了。所以 Service A 会重发 request 给 B 并且希望这次它可以得到 B 的成功响应,那么问题来了,A 应该继续重发 request 直到它成功收到 B 的响应么?

除了 transient error,还有一些别的原因可以导致请求失败。比如,request 是非法的,B 无法处理非法的 request。在这种情况下,通常 A 会收到 B 的一个显式的 error code 以表明 request 的非法性。另一个原因也可以是,B 的 bug,A 的 request 触发了 B 的 bug。在处理特定的 request 时,B 可能会 crash,deadlock,或者 hang,有 CPU Spike,或者处理 request 时非常耗时。当这其中任何一个是 root cause 时,A 重发请求反而会继续触发该 bug 并导致 B 对别的 request、别的 user、别的 service 的不可用。这就演变成了 DOS 攻击。在这种情况下,很显然 A 不应该给 B 重发请求。

在某些不确定的场合下 retry 有时也会引入额外的网络负载。如果每个人都去 retry,这就很可能导致某种 request storm (e.g. the re-mirroring storm in Amazon),最终导致网络瘫痪。

通常意义上,retry 在分布式系统中时一个处理 transient error 的好办法。但是,retry 不应该用在不确定的场合。

(1) 不要过度使用 retry。我们应该从一次 retry 到下一次 retry 降低 retry 的频率。例如,第一次 retry 的发出可以是初始 request 发出之后的 5s;第二次 retry 的发出可以是第一次 retry 后的 20s;精确的时间周期取决于系统和 request 类型。例如,初始的周期可以是 100ms,1s,5m …

(2) 限制 retry 次数。Again,retry 总数其实取决于特定的系统。它可以是 3,5,10,etc。但是它一定是有上限的。不要没完没了的 retry。如果达到次数上限时 request 仍然失败,系统肯定是有地方出了问题。这样的 event 应当被 log 下来,开发团队应当被 alert,这样他们就可以展开调查并最终解决问题。

<EOF>

posted on 2012-12-02 18:03  Cary_Fan  阅读(206)  评论(0编辑  收藏  举报

导航