首页 / 资讯中心 / 文章详情

数据采集架构的工程实践:任务调度、Redis队列与监控反哺

数据采集架构的工程实践:任务调度、Redis队列与监控反哺 ★ FEATURED ARTICLE
简介《数据清洗与采集论文》是一份面向数据分析初学者、大数据从业者及技术写作人员的参考资料聚焦大数据时代数据采集与清洗的完整流程。文档从数据采集的重要性切入介绍了通用网络爬虫与聚焦网络爬虫的差异并详细拆解了包含采集前置、任务调度中心、Redis缓存、采集器、数据传输及大数据平台Hadoop、Kafka、Spark、Elasticsearch在内的系统架构同时涵盖辅助监控系统中的信源监控、采集监控、服务器监控与数据质量校验环节。此外文档对结构化与非结构化数据源、批处理与流处理采集工具、分布式存储及分析系统选型做了梳理有助于读者理解从原始数据到可分析数据的全链路设计思路。资源为docx格式共1个文件包体大小约313KB内容层次分明便于按章节查阅。已有65人学习下载适合快速建立知识体系也可作为课程论文或技术总结的参考底稿。1. 数据清洗与采集为什么系统瓶颈不在爬虫而在任务调度与队列在数据清洗与采集的工程实践里大多数人第一次接触采集系统时都默认把网络爬虫当成主角。真正落地一套大规模采集架构之后才会发现爬虫只是最末端的执行单元决定系统能不能在高频、多信源、长时间运转下不崩的是采集前置、任务调度、Redis 队列和监控反哺这一整条链路。这篇论文描述了一套完整的工程化架构采集前置管信源和策略Redis 与调度中心管任务分派采集器只管下载和解析Kafka 与 Spark 负责传输和落地辅助监控系统兜底。搞懂这套机制比学会写几十个爬虫更能理解采集系统的底层逻辑。2. 采集前置与信源管理任务从哪来状态如何被追踪2.1 信源管理把“采集什么”变成可配置的数据对象采集前置本质上是一个信源管理系统它回答的问题只有一个系统应该去采集什么。文档里列出的信源类型包括常见网站、栏目、关键词、微信公众号、博主动态以及电子期刊、APP 客户端等。每种信源对应完全不同的采集方式网站按栏目走精确采集关键词走搜索引擎采集公众号针对特定账号监控文章列表博主针对用户主页监控动态更新。为什么一定要把信源独立成一个前置系统因为信源是动态变化的。今天要新增一个采集源明天要停掉某个栏目如果这些变动都要改代码再发版运维成本高到无法接受。采集前置把信源变成数据库里的配置项运维人员通过界面做增删改查采集器启动时拉取配置任务调度中心按配置生成任务。这个设计把“采集什么”和“怎么采集”彻底分离是整个架构的第一层解耦。信源管理的粒度也直接决定采集精确度。同一类网站只采栏目页还是连详情页一起采消耗的资源完全不同。文档里提到“栏目用于精确采集”说明信源配置项里至少包含信源 ID、信源类型、目标 URL 或接口、解析规则、采集频率、启停状态。这些字段共同决定了一个采集任务从生成到执行再到数据入库的完整路径。信源类型采集方式典型监控项网站栏目列表页 详情页解析页面可访问性、更新频率关键词搜索引擎结果页抓取关键词启停状态、结果数量微信公众号文章列表接口采集账号状态、文章更新博主动态主页时间线采集动态频率、页面结构变化电子期刊 / APP 客户端文件链接 / 接口模拟接口可用性、版本兼容2.2 正则状态与信源状态为什么说状态是采集的生命线文档里特别提到“根据信源的状态、正则状态等实时监控网站”。这里的正则状态指的是解析规则是否还有效。网页结构一旦改版原来的正则匹配不到内容解析结果就会为空。如果系统不感知这种状态就会出现一种最隐蔽的故障采集任务正常执行、日志显示成功但产出的数据全是空字段。我一般会这么理解信源状态是入口健康度正则状态是解析健康度两者必须分开监控。信源状态决定网页能不能抓得到正则状态决定抓回来能不能用。一个网站如果连续超时属于信源状态异常应该降低采集频率或暂停一个栏目如果解析空值率上升属于正则状态退化应该触发告警让运维人员更新规则。文档里说的“实时调整采集策略”本质就是对这两类状态变化做出反应。常见的错误做法是把两者混在一个监控指标里结果就是信源挂了和解析规则失效表现出的症状一样排查时要靠人工翻日志才能区分。把状态拆开是采集前置设计中一个很小但极其关键的细节。2.3 关键词采集的动态管理增删启停背后的资源账关键词搜索采集是一种特殊的信源类型。它不像网站栏目那样有固定入口而是需要实时拼接搜索词发起请求再解析搜索结果页。文档提到“便于实时增加/删除、启动/关闭采集”这句话背后是一笔非常现实的资源账每增加一个关键词就等于多了一组持续运行的采集任务。关键词数量一旦失控调度中心的压力、采集器的请求量、目标网站的封禁风险都会同步上升。所以关键词管理的核心不是增删操作本身而是启停状态机。一个关键词需要经历创建、启用、暂停、停用、删除这几个状态每个状态对应调度中心是否下发任务。暂停和启用的设计让运维人员可以在不删除配置的情况下临时调整采集负载比如某个热点事件结束后关键词可以暂停而不是删除保留历史配置方便后续复用。这个状态机和采集频率配合起来就是完整的动态策略调整。关键词热度高了就启用热度降了就暂停不会对调度中心产生持续压力。2.4 其他采集源与统一管理接口文档里提到“如电子期刊、APP 客户端等”也被纳入信源管理这说明采集前置的设计并不局限于网页。电子期刊往往有固定的 PDF 或文章链接APP 客户端需要模拟移动端接口请求。统一纳入信源管理的好处是无论底层采集方式差异多大上层都表现为一个信源、一组配置、一个任务队列。采集器只需要针对不同信源类型实现对应的适配器调度和监控逻辑完全复用。面向管理的抽象是采集前置系统真正的价值所在——它让采集架构有能力应对新出现的信源形态而不是在代码里为每一种新来源写一套独立逻辑。同时文档里提到策略调整包括“增加/删减采集器”这意味着一套正常的采集系统要支持采集器实例的水平伸缩。某个信源任务量突增增加采集器实例即可分担某个信源被停采对应实例可以释放。采集前置的配置、调度中心的队列、采集器的实例数量三者联动才能构成完整的动态调整能力。3. 任务调度与 Redis 队列唯一性保障与并发控制的底层实现3.1 为什么任务队列要放在 Redis 里数据采集层有两个核心组件Redis 缓存平台和任务调度中心。文档对 Redis 的职责描述是“缓存采集任务队列、过程数据采集状态、列表数据等”。这里需要追问一句为什么选 Redis而不是内存队列或者数据库内存队列的问题是进程重启即丢失。采集器只要一崩队列里没处理完的任务全部消失且无法追踪哪些任务丢了。数据库的问题是读写延迟和压力。采集任务的频率往往非常高每秒钟可能有成千上万个任务要入队和出队数据库在这种高吞吐场景下会变成瓶颈而且会让简单的“取一个任务”操作变得沉重。Redis 正好介于两者之间数据可以持久化防止重启丢失读写是内存级速度还支持 list、hash、zset 这些丰富的数据结构。在实际架构里任务队列通常用 Redis 的 list 结构。每个任务 ID 通过 LPUSH 进入队列采集器通过 BRPOP 阻塞弹出任务实现一个简单的生产者-消费者模型。而过程数据比如采集状态、列表页快照、解析中间结果更适合用 key-value 或 hash 结构存储并设置合理的过期时间。这样即使采集器宕机任务队列还在 Redis 里重新上线的采集器接着消费即可这是内存队列做不到的可靠性。队列 key 一般按信源类型或优先级拆分比如task_queue:news、task_queue:wechat。每个队列独立消费互不阻塞。一个信源类型的任务积压不会拖垮其他信源类型。这个过程数据的缓存策略是整个采集层吞吐能力的基础。3.2 任务调度中心频率控制与唯一性保障任务调度中心解决两个核心问题按频率触发以及保证任务处理的唯一性。按频率触发指的是任务按照信源配置的采集频率被调度比如某个栏目每 10 分钟采一次调度中心就每隔 10 分钟把这个栏目对应的任务压入 Redis 队列。唯一性保障是文档里强调的那句“同一任务同一时间只能被一个采集器处理”。为什么要这么严格因为两个采集器同时处理同一个任务会导致重复请求目标网站、重复解析、重复推送数据到下游。轻则浪费资源重则数据重复入库存量翻倍。在分布式系统里这个唯一性通常靠原子占位来实现。// 任务处理中标记保证同一任务同一时间只被一个采集器处理 String taskKey task:processing: taskId; // setIfAbsent 对应 Redis 的 SETNX 命令原子占位 // 返回 true 表示占位成功当前采集器获得处理权 // 返回 false 表示任务已被其他采集器占用 boolean acquired redisTemplate.opsForValue() .setIfAbsent(taskKey, workerId, 30, TimeUnit.MINUTES); if (acquired) { // 当前采集器获得该任务的处理权开始下载与解析 processTask(taskId); // 处理完成后释放占用让后续任务可以再次被调度 redisTemplate.delete(taskKey); } else { // 任务已被其他采集器处理直接跳过 log.info(task {} is being processed by another worker, skip, taskId); }这段伪代码背后的机制是setIfAbsent只有在该 key 不存在时才能写入成功多个采集器同时执行时只有一个能成功写入这个操作是原子的。写入时带上workerId作为值可以追溯是哪个采集器在处理这个任务。同时设置 30 分钟过期时间防止采集器崩溃后标记永远不释放——这是一个典型的“兜底”设计。这个过期时间参数是最需要小心拿捏的地方。设置得太短长任务会在处理完成前被其他采集器重新抢占导致重复处理设置得太长采集器故障后任务要等很久才能被重新调度影响数据时效性。合理的做法是根据最慢任务的预估耗时再留出余量。3.3 采集器网页下载、结构化解析与任务监控采集器是执行单元负责三件事网页下载、结构化解析、任务监控。任务从 Redis 队列里取出来采集器先根据 URL 下载网页内容再按信源配置的解析规则抽取标题、正文、发布时间等字段然后把解析结果交给数据存储层。任务监控不是写一条日志那么简单而是要把每次任务的执行状态回写到 Redis 或独立存储。文档里提到的过程数据包括“采集状态”这些状态是后面辅助监控系统做排查的数据基础。每次任务成功、失败、超时、解析为空都要有对应的状态记录。采集器还需要通过心跳机制向调度中心汇报存活状态。调度中心据此决定要不要把任务重新分配给其他采集器。如果某个采集器进程假死心跳超时调度中心就会把这个 worker 上未完成的任务重新压入队列交给其他健康 worker 处理。这个设计和唯一性保障配合起来才构成完整的“任务不丢、不重、不卡死”的调度闭环。3.4 过程数据的生命周期与延迟队列Redis 中缓存的过程数据不可能永久保留。采集状态、列表数据这类中间数据更合理的设计是统一设置 TTL比如 24 小时或 7 天到期自动清理避免 Redis 内存无限膨胀。文档里对这块的定位是“临时存储”说明设计者很清楚 Redis 不承担数据持久化职责它只是数据采集中间的流转层。如果任务处理失败需要重试可以把任务重新压入延迟队列。延迟队列基于 Redis 的 zset 实现以任务下次执行时间作为分数采集器轮询取出到期任务。这种设计的价值在于失败重试不需要立即执行可以按策略退避避免对目标网站造成集中请求压力。延迟队列是 Redis 在调度场景里非常经典的一种用法把重试逻辑从调度中心里拆出来职责更清晰。注意TTL 的策略和延迟队列的扫描间隔属于需要根据业务调优的参数。扫描太频繁会空耗 CPU扫描太稀疏会导致任务恢复不及时。一般建议延迟队列扫描间隔控制在秒级TTL 至少覆盖业务上最长的重试周期。4. 数据链路排查从采集器到 Kafka再到 Spark 消费的常见问题数据链路是采集系统里最容易出隐性故障的地方。采集器把解析好的数据通过微服务接口推送到 KafkaSpark 从 Kafka 消费后把标题、时间、正文等字段创建 ES 索引供业务查询同时把完整信息存入 HBase。这中间任何一环出问题表现都是“数据不见了”。下面这四类问题是采集架构里最高频的翻车现场每条都是真实踩过的坑。4.1 采集任务堆积Redis 队列持续增长的排查现象监控面板里 Redis 任务队列的 length 持续增长内存告警数据产出明显下降。原因调度中心按固定频率下发任务但采集器的实际处理速度跟不上。最常见诱因是某个信源页面响应变慢采集器长时间阻塞在网页下载环节另一种是解析规则退化单个任务执行时间翻倍队列消费速率随之减半。解决先看采集监控里的任务平均耗时区分是网络慢还是解析慢。如果是网络慢降低该信源采集频率如果是解析慢检查解析规则是否需要更新。架构层面则可以通过增加采集器实例来水平扩展同时调整调度中心分配给该队列的消费速率。排查时不要只盯 Redis 内存要先把积压队列对应的信源类型找出来不同信源的问题完全不相关。4.2 Kafka 数据缺失或重复推送接口与消费端的可靠性问题现象Spark 消费不到数据或者 ES 索引里出现重复文章。原因数据链路是采集器解析完后通过 SpringBoot 微服务接口推送到 Kafka。推送接口遇到网络超时时客户端重试可能导致同一数据被推送两次如果 Kafka 生产端发送失败时选择了不重试又会导致数据丢失。重复和丢失往往共存看起来是同样的现象根因完全不同。解决推送接口要做幂等设计Kafka 生产端开启重试并启用幂等生产者配置消费端按业务唯一键去重。这里的业务唯一键通常取文章 URL 的哈希或标题加发布时间的组合。Kafka 的 topic 分区数要和 Spark 消费并发度匹配避免某个分区积压而其他分区空闲。文档里提到的数据质量校验也在这个环节发挥作用推送时校验发布时间、标题、正文的解析准确度不合格的数据先落异常队列而不是直接丢弃这样后续才能反查问题根源。4.3 解析准确度翻车标题为空、正文乱码的处理现象ES 索引里某信源的标题为空正文出现大量 HTML 标签或乱码但采集任务日志显示“成功”。原因采集任务成功只代表网页下载成功结构化解析是否成功是另一回事。页面改版导致正则匹配不到标题或者网页编码识别错误导致正文乱码。文档里特别强调要校验“发布时间、标题、正文等解析的准确度”就是这个原因——下载成功和数据可用之间隔着解析规则这道关卡。解决解析规则要与信源状态关联。信源监控检测到正则状态失效时触发告警采集器对解析结果做空值检测空值率超过阈值时自动降低该信源采集优先级或暂停。在数据质量校验环节把解析异常数据单独标记用标记反查是信源配置问题还是页面结构变化。这里最常见的技术误区是只统计解析成功率不看解析结果的实际内容分布结果成功率 99% 但剩下的 1% 恰好是当天最重要的数据。4.4 漏采问题单项数据缺失时如何利用记录反查现象某个公众号的文章长时间没有入库但公众号本身在信源监控里显示正常。原因漏采往往不是单一原因导致的。可能是采集任务被调度中心跳过比如任务标记没有正常释放导致任务被误判为处理中可能是推送阶段数据被质量校验拦截比如某篇文章缺少发布时间字段被当成脏数据丢弃也可能是该信源的采集频率设置过长文章更新周期短于采集周期。解决文档给出的思路是“根据记录的状态校验网站、栏目等是否正常”。排查时先查采集监控里该信源最近的任务记录确认任务是没执行、执行失败还是执行后未推送再查数据质量校验日志。链路走到哪一步断的问题就出在哪一层。把监控记录设计成可检索的明细是漏采排查的关键——如果监控只保留汇总统计而没有明细记录这类问题基本无从查起。5. 辅助监控与数据质量四个子系统如何反哺采集策略5.1 监控系统的职责边界谁在看什么辅助监控系统包含四个子系统信源系统监控、采集监控、服务器监控、数据质量校验。它们的职责边界非常清晰互不越界信源系统监控看外部信源的健康度采集监控看内部任务的执行情况服务器监控看底层的资源占用数据质量校验看最终入库的数据能不能用。监控子系统监控对象核心作用信源系统监控网站、栏目、公众号、博主保障信源可访问及时发现页面异常采集监控采集任务状态排查异常任务、定位数据漏采服务器监控CPU、内存、硬盘、宕机状态指导采集器合理部署数据质量校验推送数据的完整性与准确性异常数据反查信源配置这四个子系统不是各干各的它们共同支撑同一个目标让采集系统具备自解释能力。任何一个环节出问题都能通过另外几个环节的监控数据交叉验证把问题定位到具体信源、具体任务、具体服务器。文档里对信源系统监控的描述是“保证其正常访问”但实际它的职责不止于此还包括栏目是否更新、公众号是否停更这类内容层面的健康判断。5.2 服务器监控与采集器部署的联动文档里有一句话值得细读“根据服务器使用情况合理部署采集器”。这意味着采集器不是均匀分布在所有机器上而是按机器负载动态调整。CPU 高的机器要减少采集器实例内存紧张的机器要避免承载大并发下载任务宕机的机器上运行的采集器要自动迁移到健康节点。这个机制和任务调度中心的唯一性保障是联动的。调度中心通过心跳感知采集器存活状态发现某个 worker 失联后把这个 worker 上未完成的任务重新分配给其他健康 worker。服务器监控在这里提供的不是任务数据而是资源数据它的作用是让调度中心在做分配决策时“有据可依”。如果采集任务的特点是大流量下载那磁盘 IO 和带宽指标比 CPU 更关键。如果任务是高并发解析CPU 就是主要瓶颈。监控指标不能一概而论要和采集任务的类型匹配。5.3 数据质量校验异常数据的反查机制文档里的描述是“主要用于实时监控数据质量根据异常数据反查信源等配置”。这是一个很容易被忽略但非常重要的设计思路。常规系统的质量校验往往是拦截式的数据不合格就丢弃记录一条日志仅此而已。但这里提到的反查机制是把异常数据当作信源配置问题的信号源而不是单纯把它当作垃圾数据。举例来说推送时发现某个栏目的发布时间字段大量解析为空反查该栏目的正则配置发现正则没有覆盖新的时间格式问题源头是解析规则退化而不是信源本身出了什么问题。要做到反查异常数据不能简单丢弃而是带着信源 ID、任务 ID、原始解析结果落到异常表里。数据质量校验还需要设定“容忍阈值”。解析空值率小幅度波动属于正常现象达到阈值才触发告警。阈值设置得太低告警会频繁打扰运维太高异常会积累到难以处理的程度。这个阈值需要按信源类型分别配置不同信源的页面结构稳定性差异很大。5.4 监控数据自身的管理与留存策略辅助监控系统本身也是数据系统。它产生信源状态变化记录、任务执行记录、服务器指标、质量校验结果这些数据量远小于业务数据但对于排障是无可替代的线索。监控数据管理有三个原则留存、可检索、与业务数据隔离。信源状态变化记录要能查到历史上某个时间点某个信源的配置和状态任务执行记录要能按信源、按时间、按结果状态检索服务器监控指标要保留足够长的历史用于容量规划。监控数据的存储建议单独使用一套存储或者独立的索引不能混在业务数据库里否则一次大规模的排障查询会拖垮业务系统的查询性能。监控数据的价值在于积累临时起意才决定开始记录等出了问题再补救历史数据就已经丢了。6. 设计取舍Kafka 缓冲、双写存储与质量校验前移这套架构里有三个设计取舍值得单独拿出来思考。第一个取舍是为什么让数据经过 Kafka而不是采集器直接写入 HBase 或 ES。采集是突发性的一个热点事件可能让任务量在几分钟内翻倍存储写入则是持续性的底层数据库和索引的写入能力有上限。如果采集器直连存储突发流量会直接把存储打垮。Kafka 在中间扮演了削峰填谷的角色采集器只负责生产消息Spark 按照存储的承受能力稳定消费。同时 Kafka 还能给数据保留一个“后悔药”窗口消费程序出了 bug 导致索引建错可以从 Kafka 重新消费修复数据。直连存储的方案做不到这一点数据一旦写进去错误就固化了。第二个取舍是 ES 与 HBase 的双写存储。文档里的设计是 Spark 消费 Kafka 数据后把标题、时间、正文等字段创建 ES 索引供业务查询同时把完整信息存入 HBase。这是典型的读写分离设计ES 擅长全文检索和条件查询但存储成本高、写入压力大HBase 擅长海量数据的高可靠存储但查询能力弱。数据进 ES 是为了“找得到”进 HBase 是为了“丢不了”。如果只存 HBase业务查询会非常痛苦如果只存 ES存储成本会随数据量线性膨胀。两个系统各司其职各用所长。第三个取舍是质量校验放在推送阶段而不是采集阶段。从直觉上看越早发现错误成本越低校验逻辑放在采集器里不是更好吗但采集器是高频执行单元它的核心职责是尽快把网页下载并解析完在采集器里做复杂的质量校验会拖慢整个采集流水线。放在推送阶段有两个好处一是推送本身就经过统一的微服务接口校验逻辑可以集中维护二是在这个环节可以借助 Kafka 的重试机制对校验失败的数据做二次确认避免把瞬时解析异常误判为数据问题。这三个取舍背后有一个共同的设计原则每一层只做一件事层与层之间靠消息队列解耦。数据采集层的 Redis 是为了让采集器和调度中心解耦存储层的 Kafka 是为了让采集和存储解耦监控系统则是为了把架构里每一层的状态暴露出来让系统具备可解释性。从那以后我每次设计采集架构都强制先画一张任务流转图把任务从信源配置生成、进入 Redis 队列、被采集器消费、推送 Kafka、Spark 消费落库的每一步状态记录和 key 命名定下来再开始写代码。因为排查采集数据丢失靠的从来不是运气而是系统在每一步留下的记录。这套架构最值得借鉴的不是某个组件的选型而是它对状态追踪的执念。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站