先给结论:限流发生时,最危险的动作不是“停下来”,而是让脚本继续重试并把失败响应覆盖到已有结果上。保护已有结果的核心是先把本次已成功返回的数据落成不可变快照,再决定是降速续跑还是改用分批补拉。选择哪一种,取决于你手上这份资料是“可重复获取”还是“过了窗口就难再取”。
把当前结果分成两种性质,后续取舍才有依据。
判断方法很直接:问一句“如果三天后再取,这份数据还会是同一个值吗”。答案是否定或不确定的,就归入时点敏感型,按下面的快照流程处理。
限流报错往往和成功响应混在同一次运行里。如果脚本用同一个变量承接每次返回,一次失败就可能把上一批好数据冲掉。
实际动作:在脚本里为每次成功响应单独写一个带批次标记的文件,例如 result_20250101_batch03.json,写入完成后置为只读。失败响应只记录到单独的日志,不写入结果目录。
这个动作的结果是:无论后续重试多少次,已落盘的数据都不会被覆盖。下一步的续跑就能从“最后成功的批次号”继续,而不是从头再来。
快照保住之后,才轮到选择恢复策略。两种做法都合理,但成立条件不同。
当剩余待取数据量不大、且限流窗口较短时,降速续跑更省事。具体做法是拉长请求间隔、减少并发,并在每次请求前检查上一次是否返回限流信号。
代价是时间被拉长。如果原本十分钟能跑完的任务变成两小时,而数据又是时点敏感型,那么在两小时内取回的数据可能跨越了统计口径的修正点,反而制造新的不一致。这种情况下降速续跑并不划算。
当数据是时点敏感型、且限流持续时间不确定时,分批补拉更稳妥。做法是按时间切片或按对象切片,把任务拆成多个小批次,每批独立落快照,失败批次单独重试。
代价是需要额外维护一份“批次完成状态”。如果没有这份状态记录,重跑时无法判断哪些批次已经成功,容易重复拉取,进一步触发限流。
假设某次任务需要拉取 30 个投放单元一周的明细,脚本跑到第 12 个单元时开始限流。
如果选择降速续跑,且限流窗口是几分钟,那么拉长间隔后大概率能在一小时内完成,此时数据口径未变,结果可用。
如果限流持续数小时,降速续跑会让前 12 个单元和后 18 个单元落在不同的数据修正时点,合并后可能出现同一指标前后矛盾。此时更合理的做法是:保留前 12 个单元的快照,把后 18 个单元按天拆成更小批次,逐批补拉,并在合并前核对重叠时间段的数值是否一致。
这里的数字只用于说明比较方法,不代表任何真实任务的耗时或规模。
有几类动作会让已有结果更难保护:
需要说明的是,限流信号本身也可能来自网络抖动、鉴权失效或请求参数错误,而不一定是触发了频次限制。把这些原因混为一谈,会导致处理方向错误。确认原因之前,先保留原始响应内容,再决定是等待还是排查参数。
综合上面几点,遇到限流时可以按这个顺序执行:
这套顺序的价值在于,它把“保护已有结果”和“继续取数”分成两个独立步骤。先做前者,后续无论选择哪种恢复方式,都不会让已经拿到的数据因为一次限流而作废。