凌晨两点十七分,我被手机震醒。不是骚扰电话,是数据质量监控平台的告警:订单表主数据重复率飙升到4.7%。你可能觉得4.7%不高?但历史基线是0.3%。这已经不是波动,是事故。
我披上衣服坐起来,打开电脑查了查——原来上游CRM系统凌晨升级,一个字段映射错了。系统没崩,数据在悄悄地烂掉。这就是典型的“闷雷”。
你可能想问,直接监控“重复率”这个指标不就行了?问题是,重复率怎么定义?按订单号?按用户ID?还是按商品+订单号组合?不同的业务定义,同一份数据能算出天差地别的结果。而这还只是单指标,多指标联合异常才是更常见的场景。
好了,言归正传。很多人以为数据质量监控就是写几条SQL查查空值、查查重复值。天真。真正能在生产环境扛住几亿行数据、能发现隐性问题、还能不被报警疲劳淹没的监控系统,底层远比你想的复杂。
一、真正要监控的不是规则,是分布
固定阈值是体检报告里的“参考范围”。你测体温37.2℃,在参考范围内,但对你个人而言,可能已经烧了。数据质量也一样。用户量从100万涨到110万,空值率从1%涨到1.2%,这算不算异常?固定阈值说算,但如果你知道这是产品新功能带来的自然波动,就不算。
所以我们的监控引擎不直接比较数值,而是比较分布形状。用到的核心算法是Wasserstein距离,也叫推土距离。它把数据分布想象成一堆土,计算移动这堆土的最小代价。代价越大,分布偏移越严重。相比传统的K-L散度,它对重叠分布更敏感,而且对称。
但原始Wasserstein距离计算成本太高,O(n³)在批数据上根本不现实。我们改用Sinkhorn近似算法,加入一个熵正则化项,能把复杂度降到O(n log n)。实际压测数据:100万行订单表,K-L散度计算需要380毫秒,而Sinkhorn只需要95毫秒。差了4倍,而且对离群点的鲁棒性更好。

二、用“多臂老虎机”做动态算法选型
静态规则有个天然缺陷:数据漂移。比如你用3σ检测交易金额异常,突然来一波双十一的促销,3σ直接炸了,报警刷屏。你以为这是系统坏了,其实这只是分布变了。
我们一开始也踩过这个坑,用孤立森林训练了一个模型,效果不错,F1达到0.82。但三个月后,用户行为模式改变,F1掉到0.61,尴尬的是我们还在傻乎乎地用它报警。
后来我们借鉴了推荐系统中的bandit思路,做了一个“多臂老虎机”选择器。每个臂对应一种算法:3σ、IQR、孤立森林、自编码器。每15分钟跑一次各算法的AUC,用UCB(置信区间上界)算法动态分配权重。这样一来,一旦某个算法开始退化,权重自动下降,其他算法补位。
那为什么不直接用多种模型投票?投票机制太死板,权重固定,等于没有动态适应。Bandit的精髓在于它不断试错,用历史的反馈调整未来的选择。这就像你家里装了多个报警器,哪个最近误报多,你就把它的音量调小,哪个报警准确,你就更信任它一些。
压测结果让人惊喜:在连续一周的人工数据漂移模拟中,固定孤立森林的F1从0.82降到0.61,而bandit机制稳定在0.77左右。虽然没法回到峰值,但它不会彻底失灵。这就像投资组合,不把鸡蛋放一个篮子里。

三、落地实践中的三个大坑

坑一:阈值拍脑袋定。很多团队喜欢设“空值率不能超过5%”这种死阈值。问题是,周一凌晨三点和周六下午两点的数据分布完全不同。我们怎么解?用STL时序分解,把数据分成趋势、季节、残差三部分,然后在残差上算3σ。这样周末的GMV自然高峰不会误报,真正的异常(比如支付接口挂了)才会触发。实测误报率下降了72%。
坑二:忽视数据血缘。好几次,下游报表全亮红灯,我们以为数据出问题了,查了半天发现是上游一个临时表被DBA清了。这就是没有血缘管理的恶果。现在我们做了血缘驱动的告警抑制:如果上游数据质量分低于60分,下游所有告警自动降级为通知。这样DBA不会半夜被无关报警吵醒,而真正的源头问题会被第一时间暴露。
坑三:监控本身的存储和计算成本失控。你以为监控是无本生意?不,全表扫描一次,1亿行记录,传统方式需要25分钟,光存储就要40GB。我们搞了两层架构:明细层用OLAP的位图索引,指标层用Redis的HyperLogLog。位图索引压缩后只有原始数据的1/20,扫描耗时从25分钟降到4分钟。更妙的是HLL用极小的空间估算基数,误差控制在0.81%以内。这些数字,是真实生产环境跑出来的。
这里想强调一个容易被忽略的偏见:数据质量监控不是“有就行”,而是“要快、要准、要省”。快体现在扫描粒度,准体现在算法自适应,省体现在存储和计算开销。
对了,还有一点:很多人觉得数据质量监控是技术活,所以忽略了它的产品体验。那你就错了。监控报表如果密密麻麻全是红色警报,没人会看。我们做了告警降噪,把告警按严重程度分级,并且支持按团队订阅。这虽然不算法,但直接决定了监控系统能不能活下来。没有产品思维的技术方案,早晚会被弃用。
最后说句掏心窝的话:监控系统的存在是为了让你能安心睡觉。如果你天天被误报折磨,要么是阈值拍脑袋,要么是算法太死板。数据质量监控不该是SQL集合,它应该是一套能自我怀疑、自我修正的机制。