豆备 DOUBAK
← 开发日志

同一张海报,换个服务器地址,档案里就多一条「改过」

111 条作品修订是凭空的,两版之间只差一个字符。而去修它之前先重量了当初记下的两个数字——两个都是错的,其中一个还把问题的性质说反了。

同一张海报,两次抓取之间只有一个字符不同:

https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2888584528.webp
https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2888584528.webp

路径一字不差,也就是同一张图。而封面地址参与「这条记录变了没有」的判定, 于是它开出一条修订——档案里多了一句「豆瓣改了这个作品」,而豆瓣什么都没改。

这件事早就记着,标着「先不修,等想清楚」。这次去想清楚, 而第一步是把当初记下的两个数字重新量一遍——两个都是错的。

错的第一个:202 是差异对,不是修订数

原来那句写的是「藏着 202 条只有分片不同的修订」。202 是相邻两版之间只有主机不同 的那些配对;其中有 91 对还带着别的字段一起变——那些修订本来就该存在, 分片只是搭了个便车。

真正凭空多出来的是 111 条,占 8172 条作品修订的 1.4%。

这个项目上个月刚在同一个形状上栽过:两组各 8 条记录,因为都是 8 就被写成了一句话, 而它们数的根本不是同一件事。两个数一样之前,先确认它们数的是同一件事。

错的第二个:豆瓣不是「按请求随机挑分片」

原来的解释是这样写的。量一遍:

扫过的图片路径436,197 条
同一份档案内,同一条路径出现两个主机的0 条
主机变过的海报589 张
其中变过两次、或者换回去过的0 张

一次抓取之内,主机永远一致;每张海报只挪过一次,没有一张挪回去。 所以不是抽样抖动,是豆瓣某个时点把图挪了一次,然后就稳在那儿。

这改变了问题的性质。不是「我们记下了噪声」,而是「我们如实记下了一次真实、 但没有意义的变化」——跟「这条短评有几个人觉得有用」「这篇日记被看了多少次」 归成一类,而不是跟「每次渲染都不一样的那种地址」归成一类。

顺带,量的过程里我自己踩了一个:

第一版扫描对压缩过的档案只印了一句「binary file matches」,一条内容都没输出。 于是「不一致 0 条」是个空循环得来的答案。

一个不可能失败的检查,证明不了任何事。加一个参数之后才是真数字。

修法:事实与索引并存,索引不覆盖事实

这个项目在另一处早就有现成的写法——档案里每个网址都存两份,一份原样,一份剥掉跟踪参数用来去重。照抄:

字段是什么参不参与判定
cover_url页面上原样那一个不参与
cover_url_key(新)抹掉量过的那一族分片主机判据是它

三条边界,每条写反了都会静默出事:

  • 只抹主机。路径里的图片编号已经唯一标识了这张图——实测 5820 个原始地址 收成 5231 个索引,而一个索引底下出现两条不同路径的:0 个
  • 尺寸那一段绝不许抹。不同尺寸是不同的字节,抹了就是两张不同的图被静默并成一张。 这是这条规则唯一会造成真数据丢失的方向。
  • 没量过的形状一律不动。档案里除了那四个分片,还真有一个别的图片主机 (出现过 4 次)。「不要把图片主机当成闭集」是这个项目吃过亏的规矩。

也没有拿索引去改写那个地址。档案里没有任何一条路径被从两个主机各抓过一次, 所以「几个分片给的字节完全一样」这句话本地证不了——改写就是在做一个没有证据的断言。

代价照说:分片变了而海报没变时不开新修订,于是 cover_url 留着的是 那条修订开张时看到的值,不保证是最新的。这是对的——一条修订的字段就是 「第一次看到它这样时页面这么说」,为一个字段破例,读者就会读错另外二十个。 最新那个地址一个字节都没丢,它在原始档案里。

「没有摘要」是个决定,所以它必须被检查

一个字段不参与判定,在数据上与「忘了给它算摘要」长得一模一样。 而后者的症状是该记的变化没记下来——只有去数才看得见。

所以豁免是明写着传进去的,而格式校验器新增一条规则:摘要的键必须等于字段的键 减去明写的豁免,少一个多一个都报错

那条一致性用例的第一版,被它自己的说明文字戳穿了

用例里放了两个作品:一个只换分片(必须只有 1 条修订),一个真的换了图(必须 2 条)。 说明文字写着「两个方向都钉」。

变异测试一跑:把封面地址整个删掉,用例照样全绿。 修订条数分毫不变——因为索引还在。而那是真的丢数据。

文字写的是本体,断言写的是代理,两者隔着三行。这是这个项目记下的第八条代理断言, 而这一条特别值得记:它是在自己的说明文字里被戳穿的。 写完「这个用例在守什么」之后回头对一遍断言,是这一族里最便宜的一道检查。

结果

改之前改之后
作品修订81728061(−111)
标记 / 广播 / 长文 / 豆列一条不动
真的换过封面的次数3535,一次不少

2967 个作品逐条比对:新的产出恰好等于把旧的「只差分片」的相邻修订压掉,其余字段零差异。

更早:桌面浏览器放行了规范禁止的东西,于是那条路看起来是通的 →