← 中文资源

简体中文版本

惊群效应

惊群效应是重试、重连或缓存失效的同步爆发,会压垮正在恢复的服务并进一步延迟恢复。

阅读英文原文

为什么同步是危险的

服务在 10:00:00 失败,一万个客户端都有 1 秒重试定时器。10:00:01 它们同时重试,服务再次承受导致故障的负载,再次失败。这个模式会持续到有人介入。客户端单独看都很合理,问题在于它们的计划同步。

同样的效应不需要故障也能出现。一小时 TTL 的缓存在启动时填充,所有条目同时过期;每天午夜运行的重算任务唤醒所有 worker;锁服务在超时后释放锁,所有等待者同时争抢。每种情况都是协调制造了容量规划没有预料到的尖峰。

打破同步

重试应使用带抖动的指数退避。延迟随尝试次数增长,随机分量把客户端分散到时间轴上:

import random


def backoff_delay(attempt: int, base: float = 0.2, cap: float = 10.0) -> float:
    exponential = min(cap, base * (2 ** attempt))
    return random.uniform(0, exponential)  # full jitter

全抖动在零和指数上限之间均匀采样,简单且有效,代价是偶尔很快重试。等量抖动保留一半固定延迟,随机化另一半,用部分分散换取最小等待。无论选择哪种策略,每次尝试都要应用,并在重试预算或截止时间耗尽时停止。

对缓存,给 TTL 加抖动,并在热点键过期前后台刷新;对锁,重试前随机等待,尽可能使用公平队列;对连接池,带抖动重连,并限制每进程重连速率。

恢复时避免惊群

恢复是最不适合出现尖峰的时刻。熔断器同时为所有人打开、负载均衡把全部流量还给刚恢复的实例、队列同时释放所有延迟消息,都可能再次压垮系统。应逐步放量、使用就绪门禁,并在爬坡期间保留并发限制。

把重试次数、重连速率和缓存未命中爆发作为一等指标。事故期间重试率上升,说明退避策略无效或客户端忽略它。目标不是消除重试,而是让重试成为受控的细流,而不是同步浪潮。

何时使用

当许多客户端可能对同一事件做出反应时,应用抖动:重试策略、重连循环、缓存刷新和计划任务。优点是恢复期负载平滑;缺点是个别调用方的平均等待略长。与固定指数退避相比,抖动用确定性换取稳定性;与共享重试服务相比,它更简单,不需要协调基础设施。