上个月,我负责的一个AI数据处理管道出了岔子。不是模型崩了,也不是服务器挂了,而是一个藏在代码深处的"幂等性"漏洞——它让同一份数据悄无声息地存了两遍。这篇文章聊聊这个坑是怎么挖的,又是怎么填的。

先解释下什么是幂等性。简单说,一个操作执行一次和执行多次,结果应该完全一样。举个例子:把变量设为0是幂等的,不管执行多少遍,结果都是0;但给变量加10就不是,每执行一次结果都变。在分布式系统里,网络中断、服务崩溃、消息重复投递都是家常便饭。如果操作不具备幂等性,同样的请求被处理两次,数据就会乱套。

打开网易新闻 查看精彩图片

问题出在一个典型的"至少一次"投递场景。我的管道结构是这样的:用户输入进来,先预处理,再丢给AI模型,最后存数据库。每个步骤失败都会自动重试。那天网络短暂抽风,第一次请求其实已经到了模型,只是响应没回来。系统判定失败,触发重试。第二次请求成功,数据入库。然后——第一次请求的响应姗姗来迟,又在后台默默存了一份同样的数据。

表面看是数据重复,不是丢失,但后果同样麻烦。如果数据库有唯一键约束,第二次写入会直接报错;如果没有,脏数据就留下了。更隐蔽的是,这种重复可能隔很久才暴露,排查起来极其费劲。

我的修复方案分三层:第一,给每个请求生成唯一ID,数据库用UPSERT(存在则更新,不存在则插入)替代纯插入;第二,在管道入口加去重层,用Redis缓存最近处理过的请求ID;第三,缩短重试间隔的同时增加"响应超时但可能已送达"的探测逻辑,避免盲目重试。

这个案例给我最深的教训是:幂等性不是"锦上添花"的优化项,而是分布式系统的底线要求。当你在消息队列(Kafka、RabbitMQ这类)或API调用里看到"至少一次"投递的保证时,脑子里就该立刻绷紧这根弦——重复消息一定会来,只是时间问题。