前几年我接过一个价格监控项目。系统刚上线时很顺,每天定时采集、清洗、入库,报表也能正常更新。运行到第三周,业务突然反馈部分商品连续两天没有数据。
排查后才发现,采集脚本没有报错,数据库也在持续写入,但目标页面的字段结构已经变化。程序把解析失败的数据当成空结果,后面的监控只检查“任务有没有完成”,所以一直显示正常。
这件事让我重新认识了数据监控:真正需要监控的不是一条脚本,而是数据从产生到使用的完整链路。
一套能长期运行的数据监控体系,至少要回答三个问题:
- 数据有没有按时拿到?
- 拿到的数据是否完整、可信?
- 出现异常后,能不能快速定位到具体环节?
先定义监控对象,再考虑技术选型
很多项目一开始就讨论用什么数据库、消息队列和告警工具,最后却说不清到底要监控什么。
我通常先把监控对象分成三层。
第一层是任务状态,包括任务是否启动、是否结束、运行耗时和重试次数。这一层解决的是“程序有没有正常工作”。
第二层是数据质量,包括采集量、空值率、重复率、字段完整率和数值波动。这一层解决的是“程序拿到的数据能不能用”。
第三层是业务结果,例如商品价格是否异常变化、某个地区的数据是否突然减少、更新频率是否偏离正常基线。这一层才是业务真正关心的结果。
只监控第一层,最容易出现“任务成功,数据错误”的情况。
采集层要留下足够的排查线索
采集程序不能只输出成功或失败。每次请求至少要记录任务编号、数据源、请求时间、响应状态、响应耗时和解析结果。
我习惯给每批任务生成唯一的 task_id,让它贯穿采集、清洗、入库和告警环节。后面查问题时,只需要拿着这个编号顺着链路找,不必在几套日志里反复对时间。
原始响应也要保留一段时间。字段规则写错、页面结构变化或者清洗逻辑误删数据时,原始数据就是复盘依据。没有原始响应,只能重新采集,碰上数据源已经更新,现场就彻底丢了。
国内公开数据采集如果需要代理接入层,我会把代理状态也记入任务日志,包括节点、连接耗时、切换次数和连续失败数。
调度和采集不要绑死
任务少的时候,用定时脚本直接启动采集没有问题。任务量增加后,调度层最好只负责分发任务,不直接承担采集逻辑。
这样做有两个好处。
一是失败任务可以单独重试,不需要把整个批次重新跑一遍。二是采集端可以水平扩展,任务多时增加执行节点,任务少时减少资源占用。
每个任务还要设置明确状态,例如:
pending → running → collected → processed → stored → completed
如果任务停在某个状态超过预期时间,系统就能判断它卡在哪一步,而不是等到整批数据没有产出才发现问题。
数据校验要分成结构和业务两道关
结构校验负责检查字段是否存在、类型是否正确、格式能否解析。业务校验则判断数据是否符合正常规律。
例如价格字段为0,从数据类型上看完全合法,但在业务上可能需要复核;某个平台当天采集量下降30%,也不一定是采集失败,可能只是数据源本身没有更新。
我一般会同时观察四组指标:
| 指标组 | 重点指标 | 主要判断 |
|---|---|---|
| 采集质量 | 成功率、超时率、响应耗时 | 链路是否稳定 |
| 数据质量 | 空值率、重复率、字段完整率 | 数据是否可用 |
| 处理状态 | 队列积压、消费耗时、失败批次 | 处理是否及时 |
| 业务结果 | 新增量、变化率、更新时间 | 结果是否合理 |
数据会说话,但要把几组指标放在一起看。采集成功率下降,同时空值率升高,问题大概率在采集链路;采集指标正常,但业务数据明显减少,则要进一步确认数据源是否发生变化。
存储要为追溯和查询分别服务
监控系统至少要保留三层数据。
原始层保存未经加工的响应,用于复盘和重新计算;明细层保存清洗后的标准记录,供业务查询;指标层保存已经聚合的监控结果,供仪表盘和告警规则直接读取。
这三层不要混在一张表里。
如果告警系统每分钟扫描海量明细数据,不仅查询成本高,还可能影响正常写入。更省心的做法,是提前计算成功率、异常量和延迟等指标,让告警系统只读取小体量的指标表。
原始数据也不必永久保存。保留多久,要看业务问题通常多久才会暴露。如果异常经常在一周后才被反馈,原始数据只留三天肯定不够用。
告警要能指导下一步动作
“任务异常,请及时处理”不算一条合格告警。
值班人员收到告警后,首先需要知道哪个任务出问题、当前值是多少、正常基线是多少、异常持续了多久,以及从哪里开始排查。
一条能用的告警至少应该包含:
- 任务名称和任务编号
- 异常指标及当前数值
- 历史基线或告警阈值
- 首次发生时间和持续时长
- 相关日志或任务详情入口
- 建议优先检查的环节
单次超时通常先重试,不必立即通知。连续多个周期失败,或者采集量、空值率和处理延迟同时异常,再升级告警。否则消息太多,真正重要的异常反而容易被忽略。
恢复通知也要保留。异常什么时候结束、持续了多久、是否经过人工处理,都是后续复盘和调整阈值的依据。
监控系统本身也需要被监控
这是搭建过程中最容易漏掉的一层。
如果告警任务自己停止运行,业务任务出错时就不会有任何提示。因此需要一条独立的心跳链路,持续检查调度服务、消息队列、指标计算和通知通道是否正常。
我通常会设置一个固定频率的测试任务,让它按完整链路产生数据并触发一条可预期记录。如果这条记录没有按时出现,就说明监控体系本身存在问题。
监控不是加几条规则就结束了。每次真实故障后,都要回头检查:为什么已有指标没有提前发现?告警是否来得太晚?排查过程缺了哪条日志?这些问题解决一次,系统才会真正稳一点。
到底怎么搭?
如果让我从零搭一套数据监控体系,我会按这个顺序推进:
先给任务和数据建立唯一标识,把整条链路串起来;然后补齐原始数据、状态日志和质量校验;再根据历史数据建立指标基线;最后配置分级告警和故障复盘机制。
代理、消息队列和数据库都是工具,不是体系本身。真正决定系统能不能长期运行的,是每个环节都可观察、每条异常都能追踪、每次故障都能留下改进结果。
实操建议也很简单:先挑一条真实任务跑完整闭环,故意制造超时、空数据、字段变化和处理积压,看看系统能不能及时发现并指出排查方向。测试环境里主动暴露的问题越多,上线以后临时翻日志的次数就越少。
常见问题
Q:小项目需要一开始就上消息队列吗?
不一定。任务少、允许整体重跑时,定时任务配合状态表已经够用。等到采集和处理速度明显不一致,或者失败任务需要独立重试,再引入消息队列。
Q:告警阈值没有历史数据怎么定?
先设置相对宽松的静态阈值,运行一到两周收集基线。等数据量和波动范围稳定后,再逐步换成按时段或任务类型区分的动态阈值。
Q:怎样区分采集失败和数据源没有更新?
同时看请求成功率、响应体大小、字段完整率和新增数据量。技术指标正常而新增量下降,更可能是数据源本身变化;多项技术指标一起异常,则优先检查采集链路。
Q:代理接入层应该重点监控什么?
不要只统计IP数量,重点看有效请求成功率、响应时间、连续失败次数和节点切换情况。如果准备接入代理商,建议直接用现有脚本测试,不要为了测试单独设计一套过于简单的请求。