跳转到主要内容

号码状态查询的重复提交:同一个号码被查了三次

月底做用量复核,发现调用次数比提交的名单条数多出两成三,名单本身已经去过重。把日志按号码聚合,同一分钟里有三个上游任务提交了高度重叠的名单。这篇讲号码状态查询的重复提交从哪来、幂等键怎么定、去重放哪一层,以及并发穿透怎么堵。

架构与性能约 1700 字

🎁 免费试用手机号码状态查询 API

直连三网运营商 · 准确率 ≥99.9% · 支持携号转网识别 · 按次计费即买即用

立即免费试用 →

月底做用量复核,数据组发现这个月的调用次数比提交的名单条数多出两成三。名单在提交前已经去过重,条数不会凭空长出来。把日志按号码聚合,答案很快浮出来:同一分钟里,三个上游任务提交了高度重叠的名单。

多出来的两成不是接口重复计费,是请求真的发了三次。这类浪费不报错,监控上只看调用量曲线,很像是最近业务量涨了。等到对账时才有人回头翻日志,一行一行看。账单上多出来的量怎么归因,号码状态查询调用量从哪来:账单高三成之后里拆过一遍;这篇只管其中一支,也就是重复提交。

号码状态查询重复提交的四个来源

来源基本集中在四处。

上游任务重叠最容易被忽略。几个业务各自维护名单,交集不小,谁也不知道隔壁也提交了同一批号。做月度经营分析的名单和催收名单,重合三成是常事。

超时重发排第二。请求超时后客户端重发一次,第一次其实已经在服务侧成功,两条各算一次调用。这类重复在接口抖动的那几天会集中出现,跟号码状态查询失败条目:重试上限与死信里那条重试链路的边界是同一处:重试要带能识别出重复的标识,否则重试本身就是新的调用量。

人工补跑排第三。任务跑到一半失败,运维习惯整批重跑,而不是只补失败的那几条,跑一次重复一次。

多入口触发排第四。定时任务和用户点立即执行撞在一起,量不大,排查时最难解释。

只用号码当幂等键,会误伤合法的查询。

同一个号码在不同业务里问的并不是同一件事:触达前问能不能发短信,合规审查问在网状态,结算问号码归属。同一分钟内这几次查询都合理,不该被当成重复拦掉。

所以幂等键通常是三段:号码、用途标识、时间窗。同一用途在同一时间窗内重复提交,第二次直接返回第一次的结论。时间窗按结论的稳定程度给,小时级或者天级都行,别设成一分钟——太短挡不住什么,太长又会把真正需要的复查吃掉。

号码状态查询任务侧去重与网关侧去重的差别

两种位置的取舍很清楚。

任务侧去重的优点是省一次网络往返,名单在提交前就瘦身。缺点是有几个上游就得实现几遍,谁漏了谁重复,而且各家时间窗的口径很难统一。

网关侧去重的好处是收口:所有上游走同一个入口,键的构成与时间窗只有一份定义,新增业务不用跟着改。代价是网关要存一份近期的键,量大的时候对存储和响应时间都是要求。

常见的做法是两层都留着。任务侧做粗去重,把明显重叠的名单先合并;网关侧做最后兜底,用统一的键和窗口再拦一道。任务侧漏了不影响总量,网关侧慢了几毫秒也没人在意。

去重逻辑最怕并发。两个 worker 在同一时刻检查,都发现这个号码之前没查过,于是各发一次请求,去重表里写进两条记录。

处理办法是在去重层加一把按号码的短锁,同一个号码在任一时刻只允许一个请求在飞,后到的那个等结果或者直接复用。锁的持有时间要卡在单次调用的超时预算之内,别让一次慢请求把整条队列堵住。

顺带一个排查经验:去重表的命中量突然掉下去,先看去重逻辑有没有被并发穿透,再去怀疑上游名单变干净了。

号码状态查询把重复率压下来的四个动作

最直接的一个指标是重复率:被去重挡下的请求数除以总提交数。

这个数字稳定在两三个点以内,说明上游名单和重试逻辑都还在控制里。超过一成,一般对应三种情况:某个上游近期的名单质量掉了、重试策略被人改过、或者有人在做大批量手工补跑。三种情况的处理方式差得很远,看重复号码的来源分布才能分清。

不设这个指标也能活,只是下次再出现两成三的偏差,还是得从日志里一行行翻。

还有一批号码无论提交几次都不会有结论:虚拟运营商放出的号段、境外运营商签发的号码,以及装在联网设备上的物联网卡。它们原本就不在覆盖范围里。名单里带上它们,只会让重复率这个指标变脏。

三个问题自测:同一份名单被两个上游提交,去重层能不能拦住?接口超时之后的重试,带不带能识别出这是一次重复的标识?去重的时间窗是统一配置的,还是每个业务各写一套?

三个都答得上来,再去看重复率的趋势,才有意义。

服务侧的去重和鉴权现成可用。直连移动、联通、电信三网,返回正常、空号、通话中、不在网、关机、无短信能力、欠费、长时间关机八种状态,支持携号转网识别,按次计费、即买即用,AppCode 随请求头一起提交——【号码实时状态检测接口】。要自己动手的仍是那把去重的键:定在哪一层、由哪几个字段组成,直接决定这次浪费能不能止住。

文章评论

发表评论

请先注册/登录后评论