Skip to content

v5.7.0 — 简易网络同步

Choose a tag to compare

@MirHuang666 MirHuang666 released this 10 Nov 01:00
· 138 commits to main since this release

本页会随勘误就地更新。规范全文以 main 为准。

这一版只回答一个问题

「好几个程序共用一个网盘目录,怎么写、怎么读,才不会把文件写坏?」

不实现任何传输协议、不绑定任何厂商——只守"文件别被写坏"这一层。

设计思想(守这三条)

  1. 我们只管纪律,不管传输:同步、加密、断点续传交给现成的网盘/服务器;
  2. 半截文件是最贵的错:宁可慢一点,也绝不让别的进程读到写了一半的东西;
  3. 删除不可逆,所以不删:删改一律移进 Archive\,宁可占空间。

步骤:写和读各一条线

写:分片(自己命名,不碰别人的)
      → 网盘可用?
          ├─ 是 → 写临时名 → rename 成正式名 → 持锁更新总索引
          └─ 否 → 追加本地队列(不丢、不阻塞)
读:只读总索引 → 按需去取某一片(不扫全目录)

断网不是异常,是预期内的分支:写不进去就排队,恢复后补交,补交幂等。

要实现什么(目标 → 机制)

目标 靠什么机制做到
多个写者不打架 各写各的分片,从"抢锁"降级成"零竞争"
观察者永不读到半截 先写 .tmp,rename 才是原子替换
总索引不被写坏 单写手 + 文件锁,拿不到锁宁可这次不写
网盘掉线不挂死 降级本地排队,--flush 幂等补交
误删可回滚 删改只移进 Archive\

细节(四条纪律 + 为什么)

  • 分片写:每个进程写自己的名字(节点__标题__时间戳),不去 append 别人在写的文件。
  • 临时名 + 改名:改名是原子操作,观察者要么看到旧文件要么看到新文件;顺带绕开
    "同步客户端在上传期锁住正式文件"的问题——被锁的只是临时名。
  • 总索引单写手:聚合视图天生只能一个人改。取锁 → 读全部行 → 删同名旧行 → 追加 → 整体重写。
  • 只移不删:删除不可逆,而多进程最常犯的错就是两边同时删。

证据

  • 未配置网盘根 → 写入返回 QUEUED,本地队列 +1,进程不挂;
  • 配好后 --flush → 队列全量补交、清空;
  • 3 个进程并发写 → 全部成功,0 个 .conflict、0 个残留 .tmp;
  • 总索引持锁重写:无重复表头、按时间倒序。

边界(没做的)

  • 真实网盘环境未验证(本机未配置 PERSONA_CLOUD);
  • Archive\ 的 GC 独立线程未实现;
  • 跨时区节点的时间戳会乱序,接第二台机器时要改 UTC。

这只是我们自己的最小实现,仅供参考。 传输、加密、重试交给现成工具即可;
四条纪律可以直接学走,甚至一行代码都不用写。我们的宗旨是:只写最小实现和可能,从不强求别人怎么做。