限流发生时,最危险的动作不是等,而是立即重试。若脚本没有把已成功返回的数据先落盘,重试会把内存中尚未写出的结果冲掉,最终只剩最后一次失败状态。保护已有结果的核心原则是:把“调用”和“保存”拆成两步,让每次成功返回都先持久化,再决定是否继续请求。
很多脚本在限流前跑得很快,返回一批就追加到列表里,直到全部跑完才统一写文件。限流一来,脚本卡在中间,列表只存在于进程内存。此时无论进程被终止、超时退出,还是你手动重跑,之前那批结果都没有独立副本。表面看是“请求被限制”,实际丢数据的原因是保存时机太晚。
这个现象有两种常见解释,需要区分清楚。
判断属于哪一种,可以做一个假设性检查:在脚本里人为插入一次失败,观察已成功返回的数据是否还在磁盘上。
这三种证据指向不同的修复动作,不能只靠“加大重试间隔”解决。
把每次成功响应视为一个不可丢的事件,处理顺序应是:解析、追加写入、记录进度、再发下一次请求。具体动作可以拆成三步。
第一步,用追加模式写入。每批结果写入独立的行或独立文件,避免整表覆盖。若工具返回的是结构化数据,可以按批次编号命名,例如 batch_0001.json,这样即使后续失败,已写出的批次仍可单独读取。
第二步,单独记录进度游标。游标可以是页码、时间戳或上一条记录的标识。它和结果数据分开保存,脚本重启时先读游标,再从下一个位置继续,而不是从第一条重新请求。
第三步,让重试有上限并区分错误类型。限流返回通常有明确信号,遇到时应等待而不是立即重发。等待时间可以按次数递增,但必须设上限;超过上限就停止并保留现场,而不是无限循环消耗配额。
做完这三步后,限流的影响范围被压缩到“当前这一批”。下一批是否继续,取决于游标是否已安全写入,而不是取决于内存里还有多少数据。
关键前提发生变化时,决策也要变。可以按以下条件判断。
一个短例子说明比较方法:假设脚本计划请求一百批,跑到第三十批时被限流。若前二十九批已各自落盘且游标停在第三十批,重启后从第三十批继续,前二十九批不受影响;若所有结果只在内存列表里,重启后从第一批开始,前二十九批的请求全部作废。两者差距不在限流本身,而在保存动作发生的时刻。
限流是外部条件,无法完全避免,但结果丢失是内部设计可以控制的。把“成功即保存”设为脚本的默认行为,比事后补救更可靠。每次调整调用逻辑时,先确认三件事:结果是否已独立落盘、进度是否可恢复、重试是否有明确上限。这三项确认过,限流就只是拖慢速度,而不是清空成果。
如果脚本还要长期运行,建议定期检查落盘文件的完整性和游标的一致性,发现不一致时先停止调用、修复写入逻辑,再恢复请求。这样下一次限流到来时,你手里始终有一份可用的已有结果。