API 拉取型管道的三个难点
从第三方 API 采集数据时,真正的难点不在解析 JSON,而在三件事:怎么确定「新数据」的边界、怎么翻页取全、出错后怎么续上。增量参数决定从哪条开始拉,分页方式决定一次能取多少,重试与退避决定失败的批次能不能自动补回来。三者任一做错,表现通常都是「任务显示成功,但数据缺了一段」。
基本信息
| 增量方式 | updated_after 时间戳、since_id、cursor 游标 |
|---|---|
| 分页方式 | offset/page 或 next_cursor,后者对数据变化更稳 |
| 可靠性 | 把请求游标落盘,失败从游标续拉 |
| 限流应对 | 识别 429 与 Retry-After,做指数退避 |
典型使用场景
- 电商平台订单与退款接口按小时增量同步到明细层
- CRM、客服系统接口定期拉取客户与工单变更
- 广告投放平台报表接口按天拉取消耗数据,用于成本分摊
- SaaS 工具开放 API 拉取用户行为日志,补充埋点数据
- 对账场景拉取支付渠道流水,要求严格不重不漏
时间戳增量 + 游标续拉
时间戳增量 + 游标续拉
STATE=/data/etl/state/orders.cursor # 保存上次拉取到的游标
TOKEN=$(cat /etc/dataops/api_token) # 令牌放权限受限文件,不要写进命令行
SINCE=$(cat $STATE 2>/dev/null || date -d '1 day ago' -Iseconds) # 首次运行回溯一天
NEXT=""
while :; do
RESP=$(curl -s -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/v1/orders?updated_after=$SINCE&cursor=$NEXT&limit=200")
echo "$RESP" | jq -r '.data[] | [.id,.updated_at,.amount] | @tsv' >> /data/etl/orders.tsv
NEXT=$(echo "$RESP" | jq -r '.next_cursor // empty') # 取下一页游标
[ -z "$NEXT" ] && break # 没有下一页就结束本轮
echo "$NEXT" > $STATE # 每页落一次状态,断点可续
done增量与分页方式对比
| 方式 | 行为 | 优点 | 坑点 |
|---|---|---|---|
| offset/page | 按页码偏移翻页 | 实现简单 | 期间有增删会漏取或重复 |
| cursor 游标 | 按服务端游标翻页 | 数据变化时依然稳定 | 游标有效期短,需及时使用 |
| 时间戳区间 | 按 updated_after 拉取 | 天然可续跑 | 同秒边界数据可能漏或跳 |
| 本地全量差分 | 拉全量后本地比对 | 口径最准 | 量大且慢,容易触发限流 |
要真正做到不重不漏,靠的是主键去重加上取数窗口重叠:每次从上次水位往前回溯几分钟重叠区间,再配合目标表 upsert,比追求精确的分区边界更可靠,也能兜住源端补数。
令牌放环境变量文件并限制权限,不要直接写在命令行参数里——shell 历史、进程列表和日志都会留下明文凭证。