实时链路的数据质量校验
流式链路的校验原则是“轻量留在线内、重型推到线外”:对每条记录做无状态检查(主键非空、金额非负、枚举合法、时间不越界),不通过的记录写入死信队列,主流程继续;跨表关联、历史全量比对这类重校验放到旁路批作业或下游质量任务里做,避免维表 join 与大范围聚合并入主链路造成反压。死信队列必须有消费方、告警与清理策略,否则它只是另一个没人看的垃圾桶。
基本信息
| 线内检查 | 无状态轻量规则:非空、范围、枚举、正则 |
|---|---|
| 错误去向 | 死信队列(DLQ)或隔离表,附带失败原因 |
| 线外检查 | 跨表关联、全量比对、基线波动放到批作业 |
| 性能约束 | 避免维表 join 与大规模聚合,防止反压 |
| DLQ 要求 | 有消费方、有告警、有清理与重放流程 |
典型使用场景
- 订单实时入仓:拦截主键为空与金额为负的记录
- 埋点数据接入:校验时间戳范围与必填字段,异常进 DLQ
- 风控实时链路:枚举取值越界直接隔离,避免下游判断出错
- 实时看板:线内只做轻量校验,波动类检查放到旁路批任务
- 故障演练:人为注入脏数据,验证 DLQ 告警与重放流程是否有效
流内旁路(Flink SQL 思路)
流内旁路(Flink SQL 思路)
-- 合法数据进主表(轻量、无状态检查)
INSERT INTO orders_clean
SELECT * FROM orders_raw
WHERE order_id IS NOT NULL
AND amount >= 0
AND status IN ('PAID','REFUND','CLOSED');
-- 非法数据进死信表,附带失败原因便于分类处理
INSERT INTO orders_dlq
SELECT *, 'invalid' AS reason, CURRENT_TIMESTAMP AS dlq_time
FROM orders_raw
WHERE NOT (order_id IS NOT NULL AND amount >= 0);
-- 说明:跨表关联与历史比对不要放进这两个语句,交给旁路批作业线内与线外分工
| 校验类型 | 放置位置 | 例子 | 原因 |
|---|---|---|---|
| 无状态单条检查 | 线内 | 非空、范围、枚举 | 开销小,可逐条执行 |
| 状态类检查 | 线内有窗口聚合 | 去重、乱序容忍 | 需窗口,但要控制状态大小 |
| 跨表关联 | 线外批作业 | 与维表核对归属 | 维表 join 易造成反压 |
| 历史比对 | 线外批作业 | 与昨日全量比对 | 数据量与资源不适合流内 |
死信队列必须有消费方与告警:没有下游处理的 DLQ 只是另一个垃圾桶,错误率上升也不会有人知道。
在实时链路里做重校验(维表 join、全量比对)会产生反压拖慢整体吞吐,甚至让上游写入被阻塞,影响面远超校验收益。
DLQ 要有重放流程:修复规则或数据后能按时间范围重放,否则错误记录只能长期堆积或丢弃。