核心做法是先冻结证据再改代码:把重复触发期间的回传日志、去重键和修复版本分别留存,修复后不要覆盖旧记录,而是用可追溯的标记把两段数据分开。这样做的直接结果是,对账时能解释差额来自哪一批重复,而不是把修复后的数字当成唯一真相。
重复触发通常有三种可区分的原因:同一用户在短时间内提交多次、回传接口被重试、页面脚本在跳转前执行了两遍。三者的证据形态不同,保留重点也不同。
这一步的实际动作是先导出一份修复前的原始回传记录,按事件ID和用户标识分组计数。如果分组后重复集中在少数键上,说明问题可定位;如果几乎每个键都出现两次,则更可能是全局脚本或回传配置问题,修复范围要放大。
面对已经产生的重复数据,有三种处理取向,但不必都用。
保留并标记适用于重复量小、且能通过事件ID区分的情况。做法是在原记录旁增加修复版本标记,让后续统计可以选择只取某一版本。前提是回传日志本身没有被覆盖,且你能拿到事件级明细。
改写汇总值适用于只掌握聚合报表、拿不到明细的情况。这时只能按已知的重复比例调整总数,但必须同时记录调整依据和假设。它的边界很明显:一旦重复不是均匀分布,按比例折算会引入新的偏差,因此只适合作为临时口径,不适合当作最终对账依据。
退出旧口径适用于重复已经污染了整段时间、且旧数据无法拆分的情况。做法是从某个明确时间点起启用新口径,并保留旧口径的截止记录。前提是你能说清切换时点,避免新旧数据在同一张报表里混用。
三种取向的共同要求是:修复动作本身要留下版本标识。没有版本标识,后续无法判断某条记录属于修复前还是修复后。
假设某次修复把去重键从“用户标识”改为“用户标识加事件类型”,修复前同一用户的不同事件会被误判为重复,修复后则不会。此时若直接比较修复前后的转化总数,会看到修复后数字上升,但这不必然代表真实转化增加,也可能只是去重口径变化。
这个例子的意义在于:修复前后记录的差异,至少有一部分来自口径本身。只有把口径差异拆出来,下一步判断“是否需要重新回传”才有依据。如果口径差异解释了大部分差额,就不必重新回传;如果仍有明显剩余差额,才需要检查是否还有未修复的重复路径。
修复上线后,可以观察回传请求量、去重命中次数和转化明细的重复率。但要注意,回传量下降或重复率归零,并不能单独证明修复正确。它们还有别的解释:回传通道临时故障、统计任务延迟、或样本期太短导致重复尚未再次出现。
更稳妥的做法是同时保留一段修复后的对照期,并确认以下条件:同一批测试事件在新旧两套逻辑下的结果可复现;修复版本标识在日志中可检索;异常回传有单独的失败记录而不是直接丢弃。满足这些条件后,才能把观察到的变化归因于修复本身。
如果这些条件不满足,下一步不是继续调报表,而是回到日志层补齐事件级记录,否则修复前后的对比始终缺少可验证的基准。
当重复只出现在个别样本、规模化后却出现例外时,不要直接把小样本结论套到全量。先确认例外样本是否来自不同渠道、不同页面版本或不同回传路径。若例外的共同点指向某个尚未覆盖的分支,那么正确动作是先给该分支加独立标记,再决定是否统一修复。
只有当你能说清重复的触发条件、影响范围和可区分键时,保留修复前后记录才有意义。否则记录越多,反而越难判断哪一段可信。把这个前提写进修复说明,比事后补一份对账表更能减少下一轮返工。