最近对 AutoClip 做了一次存储架构的彻底改造,把原先"文件系统+数据库各存一份"的双重存储模式,改成了"数据库管元数据、文件系统管实际文件"的分离存储模式。整个过程像是一场手术,先诊断病灶,再制定方案,最后开刀缝合。这篇文章先聊聊迁移的思路,下一篇再讲具体踩了哪些技术坑。
双重存储的问题在哪
原先的设计里,切片的元数据既存在数据库的 Clip 表里,又以 clips_metadata.json 的形式存在项目目录里;合集数据也一样,数据库有一份,文件系统还有一份 collections_metadata.json。甚至处理中间结果也会同时往数据库和 JSON 文件里写。
这种设计在早期开发时很方便——前后端都能直接读文件,不用查数据库。但随着项目长大,问题开始暴露:
数据冗余是最直接的。同一份数据存两处,占双倍空间,还要维护一致性。改了一边忘了另一边,轻则数据不同步,重则系统行为异常。
维护成本高。每次增删改查都要想"数据库更新了没?JSON 文件同步了没?"心智负担很重。
迁移和备份困难。因为数据散落在数据库和文件系统各处,备份时要同时抓两边,恢复时还得确保版本对齐。
目标架构:分离存储
理想的架构应该各司其职:
- 数据库:只存元数据和文件路径引用。查询快、事务安全、好备份。
- 文件系统:只存实际的大文件(视频、缩略图)。利用文件系统的天然优势,直接读写、按需加载。
这样做的好处是边界清晰:要查数据找数据库,要读文件找磁盘。没有重复,没有同步问题。
迁移策略:先备份,再动手
数据迁移最怕的是"迁到一半出错了,回不来"。所以这次制定了严格的安全策略:
第一步:全量备份到外部磁盘。迁移脚本在动手之前,会先把 SQLite 数据库和整个 data/projects/ 目录复制到 /Volumes/jf01 的备份目录里。备份完成后还要做完整性校验——对比文件数量、总大小,确认两边一致才继续。
第二步:Dry-run 预览。正式迁移前可以先跑一遍模拟,看看会涉及哪些项目、哪些文件,心里有个数。
第三步:逐项目迁移。每个项目独立处理,迁移完一个检查一个。出问题也只影响当前项目,不会全军覆没。
第四步:自动回滚。如果迁移过程中出现异常,脚本会自动从备份恢复数据库和项目文件,回到迁移前的状态。
数据清理:别忘了"历史包袱"
迁移完成后,数据库里还躺着一批"历史遗留问题":有些切片的 video_path 指向了根本不存在的旧路径;有些项目在数据库里有记录,但项目目录早就被删了。这些孤儿数据如果不清理,会一直干扰查询和统计。
清理策略是:
- 项目目录不存在的 → 连项目带切片合集全部删除
- 视频文件不存在的切片/合集 → 删除记录
- 操作前同样先备份数据库
写在最后
这次迁移本质上是一次"还债"——早期为了方便而做的妥协,后期都要还。架构设计里有一个原则我体会很深:"现在偷懒省下的每一分钟,未来都要用十倍的时间来还。"
分离存储不是唯一正确的答案,但对于 AutoClip 这个场景,它让数据边界清晰了,维护成本降低了,后续扩展也更容易了。下一篇文章,我会详细讲讲迁移过程中具体遇到了哪些技术坑,以及怎么一个个填上的。