我爱LV游 发表于 2026-10-21 17:19:58

文件算一遍指纹再比对,相同的内容就不用重传了

同一份文件被不同的人反复上传,是很常见的事。安装包、模板、会议材料,改都不改就传一遍,占的是带宽和存储。算一遍指纹先比对,已经有的就不用再传,这就是常说的秒传。

一、指纹怎么算

对整个文件做一次摘要计算,得到一个固定长度的值,内容一样值就一样。碰撞概率这件事不用过度担心,选一个成熟的算法,实际遇到的概率比磁盘坏道还低。常用的算法有几种,选哪一种主要看计算速度和碰撞概率的取舍。服务端的接收缓冲区要按并发量调,太小会频繁读写,太大会吃掉内存。

大文件算全量摘要很慢,一个几百兆的文件在手机上一算就是十几秒。折中的办法是抽样算:头一段、中间一段、尾一段,加上文件大小,凑成一个够用的标识。抽样的位置要固定,不能每次随机取,否则同一份文件两次算出来的值不一样,比对就失去意义。下载速度的限制要按用户和按接口分别做,只做一层,绕过的方式太多。

二、在哪儿算

客户端算的好处是不用传文件就能比对,省带宽;坏处是占用用户的处理器,低端机上会明显卡顿,而且客户端算出来的值不可全信。低端机上算一个几百兆的文件,风扇转起来,用户会以为应用出了问题。上传完成的回调要可靠,掉了就重试,别指望客户端一定会再发一次。

服务端算更可信,但文件已经传上来了,省带宽的意义就没了。所以顺序上要先粗后细,粗的用来筛,细的用来定,两级都便宜。比较实用的做法是客户端先算一个粗标识去查,命中之后由服务端再核一次完整摘要。完整摘要的核对可以异步做,先让用户看到上传成功,后台再核,核出问题再回滚。文件访问的权限要在服务端判,地址里带个编号就能下载,迟早会出事。

三、命中之后做什么

服务端已经有这个文件,就不用再收一遍,直接把新记录指向已有的存储,返回成功。用户侧看到的是瞬间完成,体验很好。文件的元信息单独存一张表,按业务查的时候不用去翻存储。

指向已有文件的时候要处理引用关系。一条记录被删了,不能把还在被引用的文件一起删掉。引用计数是省事的办法,减到零才真正清理。引用计数要跟删除放在同一个事务里,先减计数再删文件,顺序反了会出现文件还在、记录没了的空档。上传过程中的日志要记下分片编号,出问题的时候才知道该从哪一片查。

四、秒传的边界

秒传不能跨权限。甲用户上传了一个私密文件,乙用户算出同样的指纹,不能因此就让他拿到这个文件。这条规则要写在接口的入口处,别放在业务逻辑中间,中间一旦有分支跳过,就等于没有。命中之后必须校验归属和权限,没有权限的还是要正常上传。

这个点在实现时容易被忽略。为了省事只比对指纹就返回成功,等于开了一条绕开权限的路,而且很难在测试里发现。权限校验要按业务来,同一个公司内部可以共享,跨公司就必须拦住,这条线要写死在代码里。存两份还是存一份,要看业务的容错要求,多存一份的成本要提前算。

五、存储去重

秒传天然带来去重:同样的内容只存一份。存储层可以按摘要分目录,同一个摘要落在同一个位置,写入之前先查一下在不在。

去重也有代价。删除和迁移的逻辑变复杂,统计容量的口径也变了,按文件数算和按实际占用算,差得很远。迁移的时候要特别小心,按文件逐个搬会把一份内容搬成好几份,去重的好处一下就没了。这些口径要提前跟业务对齐。传输用的连接要复用,短连接反复握手,开销比传数据本身还大。

六、别把它当成通用手段

秒传只对完全相同的文件有效。改一个字节,指纹就变了,还是要老老实实传。对经常微调的文件,用处很有限。

上传前算指纹本身也要时间,小文件算一遍比直接传还慢。阈值按设备性能分档也可以,低端机把阈值调高,避免算指纹比传文件还久。可以按大小设一个阈值,超过才走这条路,小的就直接传。大文件的操作要有取消入口,用户点错了,得能停下来。

秒传的价值在于省掉重复的传输,不在于炫技。把权限校验和引用关系处理好,它才是一个能长期用的功能。

wxiaozhen 发表于 2026-10-21 18:22:44

这样的优质帖子越多越好,希望论坛能多一些这样真诚的交流。

兰闺蜜 发表于 2026-10-21 18:30:21

非常有建设性的意见,对解决实际问题有很大的参考意义。

llc4611377 发表于 2026-10-21 18:33:00

每一段都很有分量,认真读完全篇感觉整个人都提升了不少。

13147913681 发表于 2026-10-22 13:29:32

讲得很透彻,把复杂的问题简单化,理解起来轻松了很多。
页: [1]
查看完整版本: 文件算一遍指纹再比对,相同的内容就不用重传了