淘宝订单 API 抓数
及补偿指南
覆盖 thirdhub-scrapy-taobao 订单链路的完整原理:双表架构、主抓单水位机制、三代补偿体系、生产排期、补数手册与真实排障实录。目标:新人按本指南可以独立核对数据、执行补数、定位漏单。
开始之前 · 零基础先读
这一节不讲代码。看完你会明白:一笔淘宝订单是怎么进到我们库里的、为什么有两张表、以及为什么「抓到了」和「抓全了」是两回事。
先跟着一笔订单走一遍
假设今天 14:32 有位顾客在「kuyura可悠然旗舰店」下了一笔订单:
TaobaoIncrementOrderJobHandler 每 10 分钟跑一次,从上次抓到的位置(水位)继续,调 taobao.trades.sold.increment.get 拿到这段时间内有过变化的订单。thirdhub_shelve,routing key taobao.tradesold.{sellerId}),下游消费者落库到 tradesold_taobao_increment。self.increment.* 消息,消费者对每笔订单调 taobao.trade.fullinfo.get 拿完整明细,再推 fullinfo.* 路由,落库到 tradesold_taobao。两张表,用大白话解释
| tradesold_taobao_increment | tradesold_taobao | |
|---|---|---|
| 打个比方 | 「到货登记簿」——先记一笔再说 | 「完整档案柜」——每单一份全档 |
| 存什么 | 增量接口返回的订单(列表级字段) | fullinfo 接口拉的完整明细(收货人、子单、发票…60+ 字段) |
| 怎么写入 | 主抓单 → MQ → 下游消费者 | self 消费者逐单调 fullinfo → MQ → 下游消费者 |
| 对账口径 | trade.created(下单时间) | trade.created(下单时间) |
| 缺了会怎样 | 这单「从来没到过」,全量表必然也没有 | 「知道有这单,但详情拿不到」,下游按单处理会挂 |
| 谁负责补 | TaobaoIncrementCountCompensateJobHandler(对接口数量) | TaobaoIncrementFullInfoOrderJobHandler(对增量表逐单补) |
130 秒速览与术语表
赶时间就记住这一节:一张职责表 + 一个黄金规则。
先记住这 14 个词
| 词 | 大白话 | 在本系统里指什么 |
|---|---|---|
| 增量表 / 全量表 | 到货登记簿 / 完整档案柜 | tradesold_taobao_increment / tradesold_taobao |
| 水位 | 系统记住「上次抓到哪」 | ShopChannelTaskDTO.nextScheduleTime,按「店铺 × API」各存一条,服务重启不丢 |
| modified 抓单 | 按「修改时间」增量拉 | 主抓单用的 taobao.trades.sold.increment.get,老单有变化也能追到 |
| created 对账 | 按「下单时间」数数 | 补偿 Job 与核对脚本统一用 trade.created 切窗口 |
| needFullInfo | 抓到单后要不要顺手拉详情 | 主抓单参数,true 时全量表由 self 消费者自动写 |
| 净推进 | 每轮水位真正前进多少 | incrementSeconds − backSeconds,必须大于调度间隔才追得上 |
| 回看 | 每次多往回抓一段防漏 | backSeconds,默认 300 秒,重复抓取靠幂等消化 |
| 数量补偿 | 拿接口单量对库内单量 | 接口 total_results vs 表 count,缺哪段补哪段 |
| 幂等 | 重复跑结果不变 | 两张表都按订单号(_id)覆盖/跳过,补数可反复执行 |
| 批量接口 | 一次 POST 带多个子请求 | /router/batch,仅老 Job 使用,稳定性差已停用 |
| 单接口 | 一次一个请求 | /router/rest,现行链路全部走它 |
| 游标丢失(-5) | Mongo 翻页翻到一半断了 | 分片集群深分页 + 高负载时的经典错误,重跑安全 |
| 老单晚到 | 下单早、最近才被改 | modified 抓单会把几天前创建的单补进来,造成「历史日期缺口回涨」 |
| 北京时间 / UTC | 参数时区 ≠ 库内时区 | Job 参数填北京时间;Mongo 里存 UTC,核对时 +8 小时换算 |
sellerId 下两张表的 count。增量 = 全量 即齐;不等就按第 6 节补数。其它一切(Job 返回码、日志 true/false)都只是参考。
2双表架构与数据链路
这一节把图 0-1 展开成工程细节:三条淘宝 API、两条 MQ 路由、两个消费者、以及五个 Job 的新老关系。
2.1 用到的三条淘宝 API
| API | 按什么查 | 用途 | 谁在用 |
|---|---|---|---|
taobao.trades.sold.increment.get | modified(修改时间) | 增量拉单主入口,列表级字段 | 主抓单、Status 补偿重放 |
taobao.trades.sold.get | created(下单时间) | 按创建时间数数量 / 翻列表 | Count 补偿对账、老 Job |
taobao.trade.fullinfo.get | tid(单号) | 拉单笔完整明细 | self 消费者、FullInfo 补偿、单号直补接口 |
2.2 MQ 路由与消费者
exchange: thirdhub_shelve (topic)
taobao.tradesold.{sellerId} ← 主抓单/补偿重放,订单消息 → 下游写【增量表】
self.increment.tradesold.taobao.* ← needFullInfo=true 时附带 → self 消费者逐单调 fullinfo
fullinfo.tradesold.taobao.* ← fullinfo 结果 → 下游写【全量表】(+ 订单快照)
三条路由都不在本仓库落库——真正写 Mongo 的消费者部署在其他服务上。所以任何补偿 Job 的日志里「补偿数量 N」指的都是成功推送了 N 条消息,不等于已落库;最终以表内 count 为准。
2.3 五个 Job 的新老关系
CompensateJob、05:00 StatusCompensateJobhandler 因批量接口 500 全店失败,每天白耗配额;同日 12:57 走单接口的新补偿一次成功。功能上二者均被新链路覆盖。
3主抓单与水位机制
主抓单是唯一的新单入口。它没有 startTime/endTime 参数——时间完全由每家店的水位决定,这也是它「自动无缝衔接」和「某些坑」的共同根源。
3.1 一轮执行发生了什么
对每家开启抓单的店铺(并行 shopThreadNum 路):
startTime = 水位(nextScheduleTime) − backSeconds // 回看防漏
endTime = 水位 + incrementSeconds // 本轮抓到这
if endTime > now: endTime = now // 不允许抓未来
按 intervalSeconds 切片 → 每片: count → 按页拉单 → 发 MQ(增量路由 + self路由)
本店全部成功 → 水位推进到 endTime;任何一步失败 → 水位不动,下轮重来
3.2 参数全解
| 参数 | 默认 | 含义与建议 |
|---|---|---|
incrementSeconds | 86100(约1天) | 每轮窗口长度 = 水位推进距离。稳态关键:净推进要大于 cron 间隔 |
backSeconds | 300 | 回看秒数防接口索引延迟漏单。别低于 300,重复拉靠幂等 |
intervalSeconds | 86400 | 窗口内切片大小。600(10分钟)平衡较好;追赶时可 1800 减 count 次数 |
pageSize | 40 | 翻页大小,40 稳妥;接口允许时可试 100 |
shopThreadNum | 5 | 店铺并行度,撞限流时降到 3 |
needFullInfo | true | true = 连动全量线;self 消费者故障期间可临时 false,全量改由 FullInfo 补偿兜 |
sleep | 0 | 翻页间隔毫秒,稳态建议 500 |
3.3 日志怎么看
[店铺名]:开始执行:[2026-10-20T18:26:40]-[2026-10-20T19:11:40] ← 本轮窗口(起=回看点,止=新水位)
[店铺名]:执行:[...], api总数: 951 ← 该切片接口返回单量
[店铺名]:在:[起]-[止]时间内, api总数: N, 推送总数: M ==> true ← 一轮汇总,false 即有切片推送失败
看到窗口终点离当前时间越来越近 = 在追平;一直停在同一个时间 = 水位卡住(多半有切片持续失败,查该店铺报错)。
4补偿体系:五个 Job 的分工
三个现行补偿 Job 各管一段,参数结构相似但默认值和坑不同。逐一说明。
4.1 TaobaoIncrementCountCompensateJobHandler(补增量表)
| 做什么 | 对每店:整段对账(接口 total vs 增量表 count,按 created)→ 有缺口按 intervalMinute 切片细对 → 缺的切片翻列表挑出库里没有的 tid → 按 modified±5s 用增量接口重放 → 重推 MQ |
| 默认窗口 | 不填 = 昨天 00:00 ~ 今天 00:00;intervalMinute=60;sleep=3000 |
| 典型参数 | {"startTime":"2026-10-18 00:00:00","endTime":"2026-10-19 00:00:00","intervalMinute":60,"sleep":3000} |
| 注意 | startTime/endTime 必须成对给(只给一个会被重置为默认);无店铺过滤,全店跑;整段第一步就调一次接口 count,大跨度窗口可能被接口拒绝,建议按天拆 |
| 返回值 | SUCCESS/FAIL 只反映「最后一家有缺口的店」补偿后复核是否一致;落库有 3 秒延迟,FAIL 不代表没补上——以日志「开始补偿」和最终 count 为准 |
4.2 TaobaoIncrementFullInfoOrderJobHandler(补全量表)
| 做什么 | 对窗口(按 created 切片):数「增量表有」与「全量表有」→ 不等则逐单检查,缺的逐单调 fullinfo 推 MQ → 下游写全量表。纯 Mongo 对账 + 单号级接口,不受淘宝跨度限制 |
| 默认窗口 | 不填 = 昨天 00:00 ~ 今天 00:00;intervalMinute=60;sleep=3000;pageSize=1000;sellerId 可选(单店排查用) |
| 典型参数 | 日常兜底 {};补大缺口 {"startTime":"…","endTime":"…","intervalMinute":60,"sleep":1000,"sellerId":"808734231"} |
| 注意 | 永远返回 SUCCESS(代码无失败分支),别看 xxl-job 状态,看日志 incrementCount:fullInfoCount = x:y;skip 深分页在大促小时会翻几十页,游标丢失高危(见 8.1),大缺口按店铺拆 + intervalMinute 降到 15 |
| 能力边界 | 只能补「增量表里已有」的单;增量表缺的单它无能为力(先跑 4.1) |
4.3 TaobaoIncrementStatusCompensateJobHandler(刷订单状态)
| 做什么 | 扫窗口内「未完结状态」的单(WAIT_BUYER_PAY / WAIT_SELLER_SEND_GOODS / PAY_PENDING / SELLER_CONSIGNED_PART / TRADE_NO_CREATE_PAY / WAIT_BUYER_CONFIRM_GOODS)→ 逐单调 fullinfo 拿 modified → 重拉 modified±3s 增量重推 MQ,让下游把卡住的状态刷过来。不直接写库 |
| 默认窗口 | start = 今天00:00 − backDay,end = start + intervalDay(默认 backDay=30 / intervalDay=5,即「30天前~25天前」,直接定时跑等于白跑) |
| 定时参数 | {"backDay":1,"intervalDay":2,"statusList":[…]} → 覆盖昨天全天+今天凌晨 |
| 注意 | 很重(实测约 0.66s/单,一天未完结单几千~几万);skip 分页 + 游标丢失高危;sellerIdList 类型是 List<Integer>,13 位 sellerId 会溢出,别用 |
5生产配置:排期与参数
以「每天凌晨 01:00 前前一天订单必须齐」为 SLA 设计的排期。xxl-job 用 Quartz 六位 cron(秒 分 时 日 月 周)。
5.1 推荐排期总表
| 时间 | Job | cron | 参数 |
|---|---|---|---|
| 每 10 分钟 | TaobaoIncrementOrderJobHandler | 0 0/10 * * * ? | {"incrementSeconds":1200,"backSeconds":300,"intervalSeconds":600,"pageSize":40,"shopThreadNum":5,"needFullInfo":true,"sleep":500} |
| 00:30 | TaobaoIncrementFullInfoOrderJobHandler | 0 30 0 * * ? | {}(默认昨天) |
| 00:40 | TaobaoIncrementCountCompensateJobHandler | 0 40 0 * * ? | {}(默认昨天) |
| 00:55 | 核对(脚本/只读 Job,见第 7 节) | 0 55 0 * * ? | 对比昨天两张表 count,不等告警 |
| 04:00 | TaobaoIncrementStatusCompensateJobHandler | 0 0 4 * * ? | {"backDay":1,"intervalDay":2}(statusList 可省略) |
5.2 xxl-job 侧设置
- 主抓单:阻塞策略选「单机串行」,任务超时设 0(不限);避免上轮未完下轮触发把水位卡死。
- 补偿 Job 之间不要并发:00:30/00:40 错峰 10 分钟,白天补数时先停主抓单或错开时段,防止抢接口配额(批量接口 500 的诱因之一就是并发限流)。
- 大促日预案:主抓单 cron 临时
0 0/5 * * * ?(incrementSeconds 保持 1200,净追 5 分钟/轮);00:30 的全量兜底按店铺拆 +intervalMinute=15;00:55 核对发现缺口立即按第 6 节补,不要等第二天。
5.3 这套排期能保证什么、不能保证什么
6补数手册
按「缺什么」走对应分支。所有 Job 幂等,重复跑安全;时间参数一律北京时间;同一天只跑一个补偿 Job,不要并发。
6.1 场景 A:补增量表
识别:接口数量 > 增量表(Count 补偿日志「时间段异常, api数量:x, db数量:y」,或核对脚本报增量缺)。
Job: TaobaoIncrementCountCompensateJobHandler
按天跑(缺口大再拆半天):
{"startTime":"2026-10-18 00:00:00","endTime":"2026-10-19 00:00:00","intervalMinute":60,"sleep":3000}
- 日志判读:先「api数量/db数量」整段对账 → 「时间段异常」切片 → 「开始补偿」→ 最后「补偿后, api数量:x, db数量:y」。
- 该 Job 不能按店铺过滤,全店跑;某店持续「开始补偿但 db=0」说明下游没落该类型,别重复跑,先查消费者。
6.2 场景 B:补全量表
识别:增量 = 全量 不成立且「增量 > 全量」。
Job: TaobaoIncrementFullInfoOrderJobHandler
小缺口(<1000 单)整段跑:
{"startTime":"2026-10-16 00:00:00","endTime":"2026-10-17 00:00:00","intervalMinute":60,"sleep":1000}
大缺口(>5000 单 或 含大促小时)按店铺拆 + 15 分钟切片:
{"startTime":"2026-10-20 00:00:00","endTime":"2026-10-21 00:00:00","intervalMinute":15,"sleep":1000,"sellerId":"808734231"}
- 必跑前置:对应日期的增量表已齐(场景 A 先做)。
- 游标丢失(-5)报错时:重跑安全、幂等;若卡在某个大促小时反复失败,先算出该小时具体缺的 tid(第 7 节差集脚本),走场景 C 单号直补,让「数量相等」后该小时即被跳过。
- 它永远返回 SUCCESS——验收只看 count。
6.3 场景 C:单号直补(列表接口碰不到的单)
识别:订单号在两张表都查不到,但菜鸟单据表里有(taobao_wlb_wms_cainiao_bill.trade.orderSourceCodes 包含该单号);或核对时差集算出了具体 tid。
单笔:
POST /api/order/fullInfo
{"tid":"3316521615004026973","sellerId":"2206567129287"}
批量(每批 50~100,body 为数组):
POST /api/order/fullInfo/list
[{"tid":"…","sellerId":"…"},{"tid":"…","sellerId":"…"}]
type 字段,若是不在 TaobaoApiClient.orderType 过滤串里的类型,正是它不出现于列表接口的原因(见 9.1)。
6.4 场景 D:老单晚到 / 历史缺口回涨
识别:已经清零的历史日期,几天后核对又出现小缺口(如 10-16 从 12 单回涨到 153 单)——modified 抓单把「创建早、最近才修改」的单补进了增量表。
Job: TaobaoIncrementFullInfoOrderJobHandler
直接按 created 覆盖回涨日期重跑(老单会被一并对上):
{"startTime":"2026-10-16 00:00:00","endTime":"2026-10-17 00:00:00","intervalMinute":60,"sleep":1000}
日常预防:每周手动跑一次「最近 7 天」窗口(intervalMinute=60),比每日只兜「昨天」更能收敛这类回涨;根治方案见 9.2。
6.5 补完必验收
回到第 7 节的核对方法,目标口径:每个北京天 × 每个 sellerId,增量表 count = 全量表 count。差集为空即收工。
7核对与验收
唯一可信的验收方式:直接查 Mongo 对 count。这里给出可直接复用的口径与脚本。
7.1 时区规则(最容易踩的坑)
startTime/endTime 按北京时间解析(JVM 默认时区);Mongo 里存的是 UTC。所以查库时:北京 10-18 全天 = 库内 [10-17 16:00, 10-18 16:00)。
真实案例:曾用库内读到的
07:20 直接当参数去补,实际窗口偏了 8 小时,扫到的全是别的订单,目标单纹丝不动。换算口诀:库内 UTC + 8 = 北京时间 = Job 参数。
7.2 逐日核对脚本(北京天 × 店铺)
# 以卖家 808734231、北京 10-20 为例(窗口 = 库内 [10-19 16:00, 10-20 16:00))
inc = db.tradesold_taobao_increment.count_documents({
"sellerId": 808734231,
"trade.created": {"$gte": ISODate("2026-10-19T16:00:00Z"),
"$lt": ISODate("2026-10-20T16:00:00Z")}})
full = db.tradesold_taobao.count_documents({
"sellerId": 808734231,
"trade.created": {"$gte": ISODate("2026-10-19T16:00:00Z"),
"$lt": ISODate("2026-10-20T16:00:00Z")}})
# inc == full 即齐;inc > full 走场景 B 补全量
7.3 差集定位(找出具体缺哪些单号)
ids = [x["_id"] for x in db.tradesold_taobao_increment.find(
{"sellerId": 808734231,
"trade.created": {"$gte": ISODate("2026-10-19T16:00:00Z"),
"$lt": ISODate("2026-10-20T16:00:00Z")}}, {"_id": 1})]
have = set(x["_id"] for x in db.tradesold_taobao.find(
{"_id": {"$in": ids}}, {"_id": 1}))
missing = [t for t in ids if t not in have] # 具体缺失 tid,走场景 C 直补
大促小时(单小时 >1 万)建议加 maxTimeMS 并分批 $in,避免全表扫描超时。
7.4 在售店铺 sellerId 对照(2026-10 实测)
| sellerId | 店铺 | sellerId | 店铺 |
|---|---|---|---|
| 808734231 | kuyura可悠然旗舰店 | 2206567129287 | 第一三共海外旗舰店 |
| 2582702075 | anessa安热沙官方旗舰店 | 458450809 | MINON蜜浓海外旗舰店 |
| 328672609 | fino芬浓旗舰店 | 61991006 | 威戈官方旗舰店 |
| 1771000166 | senka珊珂官方旗舰店 | 351961830 | tmr海外旗舰店 |
| 342149215 | uno吾诺旗舰店 | 314684773 | 水之印海外旗舰店 |
店铺增减以 tradesold_snapshot_shop_config / admin 配置为准;上表是 2026-10 大促期间有单量的主集合。
8排障手册
按症状索引。每条都来自 2026-10 的真实事件,附判据与处置。
8.1 症状速查表
| 症状(日志关键词) | 根因 | 处置 |
|---|---|---|
MongoCursorNotFoundException: Cursor … not found(错误码 -5) |
分片集群(mongos)+ skip 深分页 + 高负载:游标被 shard 重启 / chunk 迁移 / 超时回收。大促小时单小时 3~4 万单,FullInfo/Status 补偿按 1000/页要翻 30~40 页,高危 | 重跑安全(幂等);预防=按店铺拆 + intervalMinute 降到 15~30;卡死的大促小时先算差集走单号直补 |
ApiException: IOException: 500 Internal Server Error(BatchFeature / BatchTaobaoClient 栈) |
批量接口 /router/batch 上游 5xx(2026-10-19 03:35~05:00 全店复现;单接口 /router/rest 同期正常) |
停用走批量的老 Job(CompensateJob / StatusCompensateJobhandler);改走单接口的新链路。网关恢复验证:GET /router/batch 返回标准淘宝错误 XML 即活 |
| 某店水位长时间不动(窗口终点不变) | 该店某切片持续失败 → 整店水位不推进(设计如此);或 xxl-job 阻塞策略把上轮顶掉了 | 看该店最近一轮报错;确认阻塞策略「单机串行」、超时 0;积压多时用追赶参数(incrementSeconds 7200 + 10 分钟内多次触发) |
| 数量补偿报「时间段异常」但补偿后 db 始终 0 | 下游消费者没在写这种类型/该店;「补偿数量」只统计推送成功,不等于落库 | 查 MQ 消费者与队列堆积;确认店铺抓单开关(admin 配置);不要反复重跑浪费配额 |
| FullInfo 补偿永远 SUCCESS 但缺口还在 | 该 Job 无失败分支,返回值不代表结果 | 以 7.2 count 为准;差集定位后按场景 B/C 处理 |
| 补数窗口跑了但目标单没进来 | 最常见:时区差 8 小时(参数该用北京时间);或该单属于「列表接口不返回」(8.4) | 按 7.1 换算重跑;仍无则查菜鸟单反查(8.4)走单号直补 |
8.2 Mongo 游标丢失(-5)详解
两个 Job 先后中招(10-19 Status 补偿第 5 页、10-21 FullInfo 补偿 10-15 20:00 大促小时的第 8 页)。共同点:分页查询发出后 1 秒内失败,说明游标刚建就被服务端判不存在——环境问题而非代码逻辑错误。让 DBA 查对应时段 mongos / shard 日志(restart、stepDown、moveChunk)可坐实具体诱因。
/api/order/fullInfo 直补;③ 数量相等后重跑补偿,该小时会被直接跳过,不再翻几十页。
8.3 批量接口 500 事件复盘(2026-10-19)
8.4 四类漏单:只有一类能被自动兜住
8.5 2026-10 事件时间线(供复盘对照)
| 时间(北京) | 事件 | 影响与处置 |
|---|---|---|
| 10-10 16:00 | 服务宕机 | 全量表断写 4 天;11 家店约 4.2 万单缺口,恢复后分批补齐 |
| 10-17 深夜 | 增量抓单停摆 | 10-18/10-19 单量暴跌(2993/164);定位为主任务水位停滞 |
| 10-19 03:35~05:00 | 批量接口 500 | 两个老 Job 全店失败;12:57 单接口链路验证成功,老 Job 停用 |
| 10-19 12:57 | Count 补偿跑通 10-17/10-18 | 增量表恢复;期间发现参数时区坑(UTC+8) |
| 10-20~10-21 | 大窗口追赶 + FullInfo 分店补 | 水位追平;10-15 20:00(40749 单/小时)触发游标丢失,改用「差集直补 2 单 + 重跑跳过」 |
| 10-21 | 菜鸟反查发现第④类漏单 | 1586 单两表皆无;确认自动兜底覆盖不了,走单号直补 + 根治建议(第 9 节) |
| 10-22 | 全链路清零 | 10-10~10-21 全部日期 增量=全量;仅当日 2 单为「刚落库待全量」的正常延迟 |
9已知局限与根治建议
现行体系的三处结构性短板与对应的改造方向,按投入产出排序。
根治:新增「菜鸟单 → 订单」兜底 Job——按
trade.modifiedTime 拉当日出库单,收集 orderSourceCodes 对两表求差集,缺的按单号调 fullinfo;同时把直补拉回的 trade.type 补进 TaobaoApiClient.orderType,让主抓单以后能自己抓到。
trade.created 对账,每日只跑「昨天」,抓不到历史日期回涨。根治:把对账字段从
trade.created 改成 createTime(增量表写入时间)——不管订单哪天下,只要新写进增量表就能兜住。小改动,收益大。过渡方案:每周手动跑一次最近 7 天。
根治:补偿 Job 改 keyset 分页(记录上页最后一条
trade.created,下页从其后取);单条处理加 try/catch 不中断整批;捕获 MongoCursorNotFoundException 从断点续跑;页大小降到 200~500。
10FAQ 16 问
按提问频率排列,答案尽量一句话给结论。
1. 补偿 Job 的日志「补偿数量 36/39」是什么意思?
成功推送了 36 条消息 / 发现缺口 39。「推送 ≠ 落库」,下游写库有延迟,最终看 count。个别差异也可能来自消息重复/合并,差 1~3 属正常。
2. 为什么 FullInfo 补偿永远显示成功?
代码里没有失败分支,恒返回 SUCCESS。它只是「跑完了」,不代表补齐了——验收必须回到 count 对比。
3. 主抓单要不要传时间参数?
不能传。它没有时间参数,窗口完全由水位算出。要补历史只能用 Count/FullInfo 补偿 Job。
4. 主抓单水位卡住怎么办?
先看该店最近一轮日志哪个切片在报错(水位只在整店成功后推进)。排掉错误后若积压多,用追赶参数 incrementSeconds=7200 + 10 分钟内多次触发。
5. 一次把 incrementSeconds 开到 60000 行不行?
行但有代价:单轮跑几十分钟,xxl-job 超时要设 0、阻塞策略单机串行;中途失败该店整段重来。更稳的做法是 7200 × 多次触发,失败只损失 2 小时进度。
6. 补偿时 startTime/endTime 只填一个行吗?
不行。判断是「或」,只填一个两个都会被重置为默认窗口(昨天),等于没填。
7. 为什么我补了,目标单还是没进表?
三查:① 时区——参数要北京时间,库内 UTC+8;② 该单是否属于第④类(列表接口不返回,只能单号直补);③ 补偿 Job 窗口是否真覆盖该单的 created。
8. 老的 CompensateJob / StatusCompensateJobhandler 还能开吗?
不能。走批量接口(已两次全店 500)、与新链路重复、绕过 MQ 直接写库。功能被 Count/FullInfo/Status 三个新 Job 完全覆盖。
9. 游标丢失(-5)会丢数据吗?
不会。只是当轮翻页中断,已处理的部分有效;重跑幂等。反复卡在同一小时就走「差集直补 + 重跑跳过」。
10. intervalMinute 越小越好吗?
不是。切片越多 count 调用越多。常规 60;大促小时 15~30;FullInfo 补偿单店小缺口 60 足够。
11. StatusCompensateJobHandler 的 intervalDay 是什么?
窗口总长度(不是往前天数)。start = 今天−backDay,end = start+intervalDay。定时用 {"backDay":1,"intervalDay":2} 覆盖昨天+今天凌晨。默认 30/5 等于只跑 25~30 天前,定时必踩坑。
12. sellerIdList 能用来只跑一家店吗?
Status 补偿的 sellerIdList 是 List<Integer>,13 位店铺号会溢出,别用。单店过滤用 FullInfo 补偿的 sellerId(字符串),或者临时在 admin 关其他店抓单开关(影响正常抓单,慎用)。
13. 怎么判断「今天主抓单活着」?
查增量表最近 1~2 小时 createTime 的写入量;或看主抓单窗口终点是否贴近当前时间。持续为 0 = 停摆。
14. 全量表偶发缺几单正常吗?
刚落库 1~2 分钟内的单(self 消费者还没处理到)属正常延迟;超过半小时还缺就是真缺,走场景 B/C。
15. 大促日要提前做什么?
主抓单 cron 提到 5 分钟;00:30 兜底改按店拆 + intervalMinute=15;00:55 核对后立即手工补,不等到第二天;04:00 状态补偿可跳过。
16. 菜鸟单据和订单表怎么互查?
订单号查仓单:db.taobao_wlb_wms_cainiao_bill.find({"trade.orderSourceCodes": "单号"});仓单反查漏单:按 trade.modifiedTime 拉窗口收集 orderSourceCodes 对两表求差集(8.4)。
11速查卡
打印贴工位。全链路只此三步:核对 → 补 → 验收。
① 核对(北京天 × 店铺)
- 口径:
trade.created,北京 10-D 全天 = 库内[10-(D-1) 16:00, 10-D 16:00) - 齐:增量 count = 全量 count
- 增量缺 → 场景 A;全量缺 → 场景 B;两表无+菜鸟有 → 场景 C
② 补(幂等,可重跑)
- A 增量:Count 补偿,按天
{"startTime":"…","endTime":"…","intervalMinute":60,"sleep":3000} - B 全量:FullInfo 补偿,大缺口按店拆 +
intervalMinute:15,可加sellerId - C 单号:
POST /api/order/fullInfo {"tid":"…","sellerId":"…"}(只写全量表)
③ 红线与口诀
- 时区:参数北京时间;库内 UTC + 8
- 净推进:incrementSeconds − backSeconds > cron 间隔
- 停用:CompensateJob / StatusCompensateJobhandler(批量接口)
- 别信:FullInfo 的 SUCCESS、补偿的「推送数」——只信 count
本文基于 thirdhub-scrapy-taobao 源码与 2026-10 生产事件整理 · 参数与 cron 以 xxl-job 实际配置为准 · 双击图表可放大