ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

采集任务中断续传:断点记录设计与实现

采集任务中断续传:断点记录设计与实现 采集任务凌晨中断重跑等于全部重来数据量一大就是灾难。断点按任务、批次、条目三级设计水位记写入值不记读取值续传三步校验对账这篇讲实现细节和踩坑。一、中断的几种死法先把问题拆开采集任务中断的原因比想象中多。网络超时只是最常见的一种实际生产里至少还有三类一是目标站点限流连续请求过多封IP进程没死但拿不到数据二是进程级故障服务器重启、内存爆掉、任务被调度系统误杀三是数据本身的问题某条记录格式异常导致解析崩溃这种最隐蔽重启后大概率还是死在同一条数据上。1. 可恢复与不可恢复要分清不是所有中断都适合续传。网络类、进程类故障数据状态是干净的续传没问题。但如果是写入端出了问题比如数据库事务没提交、消息队列堆积导致写入顺序错乱断点记录本身可能就是脏的直接续传会把错误放大。先判断中断类型再决定策略这步省不得。2. 幂等是续传的前提续传的前提是采集动作可重入。同一条数据采两次落库结果还是一条这才敢从断点附近重跑。写入逻辑不带去重续传范围就要缩小宁可多采一段再合并。很多团队续传出乱子问题不在断点在写入端不幂等。3、小结小结中断原因分清楚可恢复的谈续传不可恢复的先修数据。二、断点记录记什么三个层级的字段断点记录不是一句采到第1000页能交差的。一份能用的记录至少覆盖任务级、批次级、条目级三个层级。1. 任务级定位到具体任务实例任务级字段回答这是哪个任务的哪次执行任务ID、执行实例ID、数据源标识、启动时间。为什么需要实例ID同一个任务可能被并发跑两份不区分实例两份进程读写同一个断点文件记录互相覆盖。这个坑踩过一次排查一下午才发现是运维同时起了两个容器两边的断点互相打架进度条忽进忽退。2. 批次级定位到采集的进度点批次级字段是断点的主体回答采到哪了。分页拉取的记页码加排序参数、上一页最后一条的游标值增量拉取的记时间戳水位或自增ID水位。这里有个细节水位要记已成功写入的最大值而不是已读取的最大值。读到了但没写进去重启后跳过这段就是数据丢失。3. 条目级明细清单应对精细回补条目级记录最重但数据价值高的场景不能省。每采一条把唯一键追加到清单里续传时对着清单查漏。清单可以放Redis的Set也可以落本地文件按批次分片。代价是写入开销大适合字段价值高、总量可控的源比如订单类、交易类数据。一份简化后的断点记录{task_id:sync_member_09,instance_id:20260906-xx81,source:erp_member,mode:cursor,cursor_field:updated_at,cursor_value:2026-09-06 14:22:31,last_page:47,written_count:23250}written_count看着多余其实是对账时核对总数的关键第四节专门讲。4、小结小结断点按任务、批次、条目三级设计水位记写入值而不是读取值。三、什么时候写落盘时机的三种选择断点什么时候落盘直接决定续传后要回补多少。常见三种时机。1. 每页写一次分页采集最自然的做法每拉完一页、写库成功后更新断点。粒度适中中断后最多重采一页。大多数场景够用实现也简单断点更新和翻页写在同一个循环里出问题好排查。2. 每条写一次条目级场景的做法每条数据写入成功就更新断点。安全性最高但断点写入本身成了瓶颈高频场景下写断点的次数比业务数据还多。折中办法是攒批比如每50条刷一次同时保证这50条写入的原子性要么都算数要么都不算。3. 定时写按时间间隔落盘比如每30秒一次。适合单批数据量大、处理时间长的任务一批跑十几分钟每页写的粒度就太粗了。定时写要配合条目级去重清单否则中间那段写没写进去重启后无从判断。实际项目里通常是组合拳批次级断点每页写条目级清单攒批写任务级状态定时写。用的搭贝做采集调度时断点状态可以直接挂在任务配置里统一管理平台按用户数报价小团队也扛得住。4、小结小结落盘粒度按数据价值选价值越高写得越勤。四、续传时怎么对账三步校验有了断点记录重启后的续传要固定成动作不能凭手感。建议三步。1. 先读记录再核对环境续传第一步不是直接跑而是读断点、核对环境数据源表结构有没有变、分页参数还能不能用、水位字段是否有效。源端结构一变旧断点直接失效硬跑只会产出脏数据清洗的代价比重采还高。2. 用written_count对总数拿断点里的written_count跟目标库实际落库数比对。一致断点干净从水位之后接着采目标库多了有重复写入先去重少了说明有读了没写进去的回补范围往前扩。这步对账做扎实能挡住绝大多数静默丢失比任何告警都直接。3. 重叠窗口回采对账之后别从水位的精确位置开始往前多拉一段比如退一页或退五分钟的时间窗重叠区靠唯一键去重兜底。原因很实际断点落盘和业务写入之间永远有时间差精确续传看着优雅实际总在边界上丢数据。用一点冗余计算换确定性这笔账划算。4、小结小结读记录、对总数、留重叠三步走完再开采集。五、多数据源场景断点要隔离真实项目没人只采一个源。多个数据源、多个适配器并行跑断点记录的隔离就成了设计重点也最容易踩坑。1. 按源建命名空间断点存储的key带上数据源标识比如 source:erp_member:cursor 和 source:crm_order:cursor 分开存。见过把所有源的水位写在同一个配置文件里的一个适配器升级时配置回滚其他源的水位跟着回退凭空多采了一整天的数据。有幂等兜底没出乱子但排查起来折腾半天就耗在这上面。2. 适配器各自管断点格式不同源的增量标识不一样有的靠时间戳有的靠自增ID有的靠变更日志序号。适配器层各自定义断点结构调度层只管存取、不解析内容。接入新源不用动公共代码一个适配器改字段也不影响其他源边界清楚。3、小结小结断点按源隔离格式由适配器自理调度层只做存取。六、调度器与断点的配合断点续传不是采集进程单方面的事调度器的行为直接影响续传效果两边得咬合好。1. 重启次数与退避任务失败后调度器会自动重启但要设重启上限和退避间隔。目标站点限流时无间隔地反复重启等于火上浇油IP封得更死。合理做法是指数退避连续失败达到上限就告警转人工而不是无限重试把小问题拖成大故障。2. 断点过期处理断点不是永久有效的。源端数据滚动清理、接口改版都会让旧断点失效。给断点记录加创建时间超过阈值比如7天的断点续传前强制走一遍环境核对核对不过就降级为全量采。宁可慢一点不能错一截。调度这块如果直接用搭贝的采集任务管理重启策略和断点状态查看都是现成的不用自己养一套守护进程对一个人兼着写采集和运维的小团队来说省出来的时间比什么都实在。3、小结小结调度器管重启节奏断点管进度位置职责分清。七、常见问题Q断点记录存哪里合适文件还是数据库A单机小任务用本地文件加定期备份就够。多实例部署或容器环境本地文件随容器销毁放Redis或数据库更稳。判断标准就一条断点存储的寿命要长于任务进程的寿命。Q增量采集用时间戳水位为什么总丢数据A大概率是边界问题。时间戳只精确到秒同一秒内有多条记录水位卡在中间用大于判断就会漏掉同秒的后续记录。改成大于等于再配合重叠回采和唯一键去重宁可多采不能漏采。Q断点更新失败但数据写成功了怎么办A这正是written_count对账要抓的场景。落库数多于断点计数续传会多采一段靠幂等去重兜底问题不大。反过来才危险断点更新了但数据没写进去跳过的就是真丢。断点更新必须放在业务写入成功之后顺序不能反。Q全量重跑和断点续传怎么选A看数据量和源端承受力。百万级以内、接口扛得住全量重跑加去重反而省心。数据量大、采集周期长续传的时间优势才体现出来。断点过期、环境核对不过关的直接全量别硬续。
返回列表