冷门资源的常规做法是"赛马":把同一部影片的所有候选种子一起投上,等一两分钟,然后把慢的删掉,只留最快的那条继续跑。这个策略本身没问题,但删输家的那一下如果点错了选项,很可能会把赢家需要的文件一起删掉。
现象
删掉慢候选之后,几个诡异的症状一起出现了:
- 留在客户端里、本该继续下载的那个最快任务,进度突然对不上了——文件没了;
- 但客户端界面上,它仍然显示 100%,看上去好端端的;
- 直到手动触发一次"重新校验",客户端才发现文件不在了,把进度一路回退。
也就是说,"删除慢候选"这个动作,删掉的东西比你以为的多。
根因
根因是:同一内容的不同种子,常常共用同一个文件夹名和文件名。
它们是同一部影片、同一个压制版本的不同发布,文件目录结构大同小异——甚至完全一致。当你对慢候选执行"连文件一起删除"时,客户端按文件名去删,删的正是那条路径上的文件;而赢家任务用的也是同一条路径、同一批文件。于是慢候选的任务记录没了,但它指向的那批文件也没了,赢家瞬间失去了自己的数据。
至于"仍然显示 100%":客户端的状态是缓存的,它不会在文件被外部删除后主动去核对磁盘。必须重新校验一次,它才会逐块对比文件与记录,把对不上的部分标记为待下载。这也意味着,如果没去校验,你会以为一切正常,等到需要读取文件的那一刻才发现是空的。
解决
规则很简单:赛马删输家时,绝不能带"连文件一起删"的选项。
- 只删任务(remove torrent),保留文件;
- 让真正要留的那条任务继续持有这些文件;
- 事后清理残留:删掉任务、确认赢家跑完之后,再手动清掉文件夹里多余的零碎文件(比如各版本附带的说明、样本、多余的音轨)。
如果客户端支持,更好的做法是让所有候选指向同一个文件夹,这样无论哪条胜出,用的都是同一批已下载数据,谁也不会白跑。反过来,如果一开始就把每条候选放到各自独立的子目录,虽然能避免误删,但每条都要从零下载,赛马的意义就没了——这是一个需要提前想清楚的取舍。
排查这类问题时,第一件事是去磁盘上看文件到底在不在,而不是相信客户端界面上的进度。界面是任务的视图,磁盘才是事实。
延伸与预防
这条坑的通用教训是:多个任务可能指向同一批文件,操作时一定要分清"删任务"和"删文件"。
这类"共享资源被隐式删除"的模式在很多地方都会出现:
- 硬链接 / 符号链接:删掉一个"看起来是副本"的目录,其实删的是共同指向的真实文件;
- 容器卷:
docker compose down -v里那个-v,会把卷一起删掉,而卷里可能是你数据库的全部数据; - 多版本软件目录:几个版本共享同一份配置或缓存,清理旧版本时连带清了共享部分(相关内容在"版本号不等于正在运行的那个文件"一条里有详细展开)。
一个通用习惯:任何带"连同数据一起删"语义的按钮或参数,点之前先数一遍"还有谁在用这些数据"。 客户端把两者做成两个不同的选项,本身就是在提醒你它们不是一回事。