本实战采用经典的 Master-Worker 集群架构模式,由一个 Master 协调节点、N 个采集 Worker 节点和一个聚合 Worker 节点组成。Master 节点负责任务的分解、调度以及 Worker 节点的生命周期管理;采集 Worker 节点负责具体的数据抓取和初步清洗工作;聚合 Worker 节点负责最终的数据合并、关联分析和结果输出。
核心架构:1 个 Master + N 个采集 Worker + 1 个聚合 Worker,三者通过共享目录和消息队列进行通信协调。
Master 是集群的大脑,它的职责包括:接收用户提交的数据采集任务、将任务拆分为多个可并行执行的子任务、为每个子任务选择合适的 Worker 节点、监控 Worker 的执行状态并在 Worker 失效时重新调度、以及最终通知聚合 Worker 开始汇总工作。Master 节点本身不参与具体的数据抓取,确保其能够专注于协调和调度。
每个采集 Worker 运行在独立的进程中,拥有自己的网络连接池和数据处理管道。Worker 从 Master 接收任务指令后,按照指定的数据源发起 HTTP 请求,解析返回的数据格式(JSON、XML 或 HTML),执行字段提取和初步的格式转换,最后将清洗后的数据写入共享的临时目录中。每个 Worker 处理的原始数据量建议控制在 100MB 以内,以保证单次处理的稳定性和内存使用的可控性。
聚合 Worker 在所有采集 Worker 完成任务后启动。它读取共享目录中所有 Worker 输出的中间数据文件,按照配置的关联规则进行数据合并,执行跨数据源的交叉验证,进行最终的统计汇总,并将结果写入指定的输出文件。聚合阶段是保证最终数据质量和一致性的关键步骤。
数据源分配是影响集群效率的核心因素。合理的分配策略能够最大化并行度、最小化等待时间、并有效规避数据源的频率限制。以下是四种常用的分配策略及其适用场景。
这是最直观的策略:每个采集 Worker 负责一个或多个独立的数据源(API 端点或网站)。例如,如果需要从天气 API、股票 API 和新闻 API 三个不同的数据源采集数据,可以将这三个数据源分别分配给三个不同的 Worker。这种策略的优点是 Worker 之间完全独立,无需协调,且每个 Worker 可以根据数据源的特点定制采集逻辑。缺点是如果某个数据源的数据量特别大,对应的 Worker 会成为瓶颈。
当数据源是同一个但数据量巨大时(例如需要爬取一整年的历史数据),可以按日期范围或 ID 范围进行分割。将 1 月到 3 月分配给 Worker 1,4 月到 6 月分配给 Worker 2,以此类推。这种策略能够有效利用多个 Worker 并行处理同一数据源,大幅缩短总体采集时间。适用于分页 API 或时间序列类数据。
如果同一数据源提供多种类型的数据,可以按数据类型进行拆分。例如,一个电商 API 可能同时提供商品信息、用户评论、订单记录和物流追踪四类数据。这种情况下,可以让不同 Worker 分别采集不同类型的数据,每个 Worker 专注于一种数据格式的处理逻辑。这种策略的优势是采集逻辑相对单一,代码复用率高。
实际场景中,数据源通常有请求频率限制(Rate Limit)。如果多个 Worker 同时访问同一数据源,可能导致请求被限流或封禁。因此,在分配时需要考虑:对同一数据源的访问应尽量集中到少数 Worker 上以便控制总请求速率;为 Worker 配置请求间隔和退避策略;将高频率限制的数据源和低频率限制的数据源混合分配给同一个 Worker,实现负载均衡。Master 节点在分配时应当读取数据源的限流配置,计算合理的分配方案。
采集到的原始数据往往包含噪声、重复、格式不一致等问题。本实战采用"边采集边清洗"的策略,让每个采集 Worker 在完成数据抓取后立即执行清洗流程,而不是将所有原始数据集中到聚合阶段再统一清洗。这种策略可以减轻聚合节点的负担,并在早期发现数据质量问题。
所有 Worker 遵循相同的清洗规则集合,确保数据的一致性。清洗规则涵盖以下方面:
每个 Worker 清洗完成后,将数据输出为统一的 JSON Lines 格式(每行一条 JSON 记录),写入共享存储目录。文件名包含 Worker ID 和时间戳以确保唯一性。同时,每个 Worker 生成一个对应的数据清单文件,记录该批次数据的数量、时间范围和异常统计信息。
清洗过程中发现的每个问题都会被记录:缺失字段有哪些、异常值内容和原因、重复记录的数量。这些质量问题记录会随同清洗后的数据一起写入共享目录,供聚合阶段参考。聚合 Worker 在最终报告中会汇总所有质量问题,形成完整的数据质量报告。
聚合阶段是整个数据采集流程的收官环节。聚合 Worker 读取所有清洗后的数据文件,按指定规则关联不同数据源的数据,执行统计分析,最终输出统一格式的结果文件。聚合过程分为三个子阶段:数据关联、汇总统计、结果输出。
不同的采集 Worker 可能从不同数据源获取了同一实体的不同维度的数据。例如,Worker 1 从天气 API 获取了某城市每日温度数据,Worker 2 从空气质量 API 获取了同一城市同期的 AQI 数据。聚合时,需要按城市和日期作为主键进行关联,形成一条包含温度和 AQI 的完整记录。关联策略包括内关联(仅保留所有数据源都有的记录)和外关联(保留一个数据源的全部记录,缺失字段填充默认值),具体策略取决于业务需求。
关联完成后的数据可以进行多种统计分析:计算数值字段的总数、平均值、中位数、标准差等统计量;分析数据的时间分布和地域分布;识别趋势和异常模式。汇总统计的结果既可以作为最终输出的一部分,也可以用于生成可视化图表的数据源。
最终结果以两种格式输出:一种是完整的 JSON 格式数据文件,包含所有采集和清洗后的记录以及质量标记;另一种是摘要格式的 CSV 报告,包含统计汇总信息和关键指标的概览。输出文件的命名格式为 result_YYYYMMDD_HHMMSS.json 和 summary_YYYYMMDD_HHMMSS.csv,方便按时间排序和查找。
数据采集和处理过程中,异常是常态而非意外。一个健壮的集群必须具备完善的异常处理机制,确保在部分组件失效时整体任务仍能完成,或至少能够优雅地降级并提供详细的错误报告。
当采集 Worker 无法连接到数据源时,首先进行指数退避重试:第一次重试等待 1 秒,第二次 2 秒,第三次 4 秒,以此类推,最大等待时间为 60 秒。连续重试 5 次仍然失败后,Worker 将当前数据源标记为不可用,记录错误详情,并继续处理下一个数据源。Master 节点会汇总所有不可用的数据源信息,在最终报告中列出。
在数据关联阶段,可能会发现某些实体在部分数据源中完全没有记录。对于这种部分数据缺失的情况,聚合 Worker 采用以下填补策略:对于数值型字段,使用该字段在所有现有记录中的平均值或中位数填充,并在字段名后添加 _imputed 标记;对于类别型字段,使用 "unknown" 填充;对于时间序列数据,允许一定间隔的缺失(不超过连续 3 个时间点),超出则标记为数据空洞。所有填补操作都会被记录,确保数据使用方能够区分真实数据和填补数据。
聚合完成后,执行一致性验证:检查每条记录的主键是否唯一;验证数值字段是否在合理范围内(如温度不高于 100 摄氏度、日期不晚于当前时间);确认关联后的记录中各字段之间没有逻辑矛盾(如发货日期不早于下单日期)。验证不通过的记录将被标记为可疑,单独写入一个异常记录文件中,不纳入最终的统计汇总,但保留在完整数据集中供人工复核。
每个采集 Worker 在运行过程中定期向 Master 上报进度:当前正在处理的数据源、已采集的记录数、已失败的请求数、当前内存使用量等。Master 节点汇总所有 Worker 的进度信息,每 30 秒生成一次进度报告。进度报告可以通过控制台输出、写入日志文件或通过 HTTP 接口查询。Master 还会检测 Worker 的心跳,如果某个 Worker 超过 30 秒未上报心跳,Master 将认为该 Worker 已崩溃,并重新分配其任务给其他 Worker。
异常处理的核心原则:对外部依赖不信任、对异常提前预防、对失败优雅降级、对每个异常记录留痕。只有在异常处理机制到位的前提下,数据采集集群才具备真正意义上的生产可用性。