云存储 / 网盘 架构模板
代表产品:Dropbox、Google Drive、iCloud、OneDrive、百度网盘 一句话定位:把用户的文件可靠地存到云端,在多设备间自动同步,做到不丢、不重复占空间、断了能续传。
1. 一句话定位
云存储 = 一套小而关键的「元数据」(目录树、版本、块清单) + 一片近乎无限的「内容块」存储,两者分离。
它最核心的一招是:把大文件切成小块(chunk)。 你后面会看到,断点续传、增量同步(只传改动的块)、去重(相同的块只存一份)——这些看起来很神的能力,全都是「分块」这一个决定的副产品。
2. 业务本质:它在解决什么问题
它解决的是「我的文件,在任何设备上都能拿到、永远不会丢、且各设备保持一致」。把文件从「绑死在某台电脑硬盘上」变成「跟着账号走、随处可得」。
钱从哪来:存储容量订阅(免费几个 G,要更多就付费)、企业版的协作 / 合规 / 管控、API 与生态。
关键事实:这类系统里,「存储成本」和「带宽成本」是两座大山。 所以「相同内容不重复存」「只传变化的部分」不是锦上添花,而是商业模式能否成立的关键。
3. 核心需求与约束
功能性需求:
- [ ] 上传 / 下载文件
- [ ] 多设备自动同步
- [ ] 文件夹、共享、协作
- [ ] 版本历史、回收站
- [ ] 断点续传(大文件传一半断了能接着传)
非功能性需求 / 质量属性:
| 质量属性 | 目标 | 为什么对这类系统重要 |
|---|---|---|
| 持久性 | 几乎不丢(如 11 个 9) | 用户把它当「最后的保险箱」,丢文件是致命的 |
| 带宽效率 | 只传变化的部分 | 改一个字不该重传整个文件,省钱省时 |
| 同步一致性 | 多设备最终一致 | 各设备看到的目录树要收敛一致 |
| 成本 | 存储越省越好 | 去重、冷热分层直接决定毛利 |
关键约束(不可逾越的边界):
- 🔴 文件可能极大(几个 GB),网络不稳定 → 必须能断点续传、分块传输。
- 🔴 设备会离线,离线期间多端可能改同一文件 → 会产生冲突。
- 🔴 持久性是底线:可以慢,但绝不能丢。
4. 架构全景图
设备 A(同步代理) 设备 B(同步代理)
┌────────────────────┐ ┌────────────────────┐
│ • 监测文件变化 │ │ • 收到同步通知 │
│ • 切块 + 算每块哈希 │ │ • 只下载缺失的块 │
└─────────┬──────────┘ └──────────▲─────────┘
│ ① 上传前先问:这些块你有没有? │ ④ 通知:有新版本
▼ │
┌────────────────────────┐ ┌──────────────┴───────────┐
│ 元数据服务 │ │ 同步协调 / 通知 │
│ 目录树 / 版本 / 块清单 │◀───────▶│ (谁该更新了) │
│ (小、强一致、频繁查) │ └──────────────────────────┘
└───────────┬────────────┘
│ ② 只上传服务端没有的块
▼
┌────────────────────────────────────────┐
│ 块存储(对象存储) │
│ 按【内容哈希】寻址 → 相同内容自动去重 │
│ (大、不可变、近乎无限扩展) │
└────────────────────────────────────────┘灵魂是「元数据 ↔ 内容块」的分离:元数据小、要强一致、被频繁查改;内容块大、不可变、用对象存储近乎无限堆。把它俩分开,各用最合适的存储,是这个系统所有效率的来源。
5. 组件职责
- 客户端同步代理:监测本地文件变化、把文件切块、算每块哈希、决定哪些块要传 / 要下。为什么需要:增量同步和去重的智能,大部分发生在客户端。
- 元数据服务:保存目录树、文件版本、每个文件由哪些块组成(块清单)。为什么需要:它是「文件长什么样」的真相源,小而关键,要强一致。
- 块存储(对象存储):存所有内容块,按内容哈希寻址。为什么需要:海量、不可变的大数据最适合对象存储;内容寻址带来天然去重。
- 去重:相同哈希的块只存一份。为什么需要:这是省存储成本的核心。
- 同步协调 / 通知:文件变了,通知其他设备来拉。为什么需要:多设备一致靠它驱动。
6. 关键数据流
场景一:上传一个文件(分块 + 去重 + 只传缺失)
1. 同步代理把文件切成块,算每块哈希:[h1, h2, h3, h4]
2. 先问元数据服务:这几个块你有吗?
服务端答:h1、h3 我有了(别人传过 / 你传过)
3. 只上传 h2、h4 两个块 ──▶ 块存储
4. 更新元数据:这个文件 = [h1, h2, h3, h4],版本 +1
── 结果:能去重的块一个字节都不重传场景二:改动文件后增量同步
你在一个 1GB 文件末尾改了几行:
切块后发现只有最后 1~2 个块的哈希变了
──▶ 只上传那 1~2 个变化的块,其余原封不动
── 这就是「改一点只传一点」,而不是重传 1GB7. 数据模型与存储选择
核心实体:文件 / 文件夹(元数据:路径、版本、块清单);块(内容哈希 → 数据);用户 / 配额。
| 数据 | 存储类型 | 为什么 |
|---|---|---|
| 目录树 / 版本 / 块清单 | 关系型(强一致) | 频繁查改、要事务、是「文件结构」的真相 |
| 内容块 | 对象存储(内容寻址) | 海量、不可变、按哈希取、天然去重 |
| 冷数据 / 老版本 | 廉价归档存储 | 很少访问,放冷存储省钱 |
| 同步状态 | KV / 内存 | 高频、设备级 |
教学点:用「内容哈希」当块的 ID,相同内容自然得到相同 ID、只存一份——这就是去重。Git 存对象、容器镜像分层,用的都是这套「内容寻址」。
8. 关键架构决策与权衡 ⭐
决策 1:整文件存储,还是分块存储?(一切能力的源头)⭐
- 整文件:简单,但改一个字要重传整个文件、传一半断了要重来、相同文件存很多份。
- 分块:把文件切成固定 / 可变大小的块。
- 取向:必然分块。断点续传、增量同步、去重、并行传输——全是分块的副产品。 代价是要维护「文件 → 块清单」的映射和块的生命周期。
决策 2:块用「内容寻址」(哈希当 ID)⭐
- 用随机 ID / 路径当块标识:相同内容会被当成不同块,存很多份。
- 用内容哈希当块 ID:相同内容 → 相同哈希 → 自动只存一份。
- 取向:内容寻址。它让去重变成存储的自然属性,而不用额外比对。代价是哈希计算开销、和极小概率哈希碰撞的处理。
决策 3:元数据和内容,分开存 ⭐
- 混在一起:大文件和小元数据用同一种存储,两头都不讨好。
- 分离:元数据(小、强一致、频繁)用关系型;内容(大、不变、海量)用对象存储。
- 取向:必分。这是「按数据的访问形态选存储」的标准范例。
决策 4:多设备离线改同一文件,冲突怎么办?
- 后同步的覆盖先的:简单,但会丢数据。
- 检测到冲突时保留两个版本(生成「冲突副本」),交给用户决定。
- 取向:宁可留冲突副本,也不静默覆盖。和 协同文档 一样:保留,而非覆盖。
9. 规模化与瓶颈
- 第一个瓶颈:元数据服务随用户和文件数膨胀。 → 破解:按用户分片(一个用户的文件树落在一处,查询不跨片)。
- 第二个瓶颈:内容存储规模。 → 破解:对象存储天生近乎无限扩展;配合去重和冷热分层压成本。
- 第三个瓶颈:同步通知的扇出(一个改动要通知用户的所有设备)。→ 破解:发布 - 订阅 + 长连接,见 通知系统模板。
- 第四个瓶颈:热点文件被海量分享下载。 → 破解:CDN 缓存分发,见 视频流媒体模板。
10. 安全与合规要点
- 加密:传输加密 + 静态加密是底线;高敏场景上端到端加密(但 E2EE 下服务端做不了去重和云端预览,是真实取舍)。
- 共享权限:链接可见范围、过期、密码、只读 / 可编辑。
- 数据隔离与驻留:多租户隔离;企业 / 监管可能要求数据存在特定地域。
- 滥用治理:防止被用来存 / 传违法内容,需要合规检测机制。
11. 常见误区 / 反模式
- ❌ 整文件传输,改一个字重传整个文件 → ✅ 分块 + 增量,只传变化的块。
- ❌ 元数据和内容混在一种存储里 → ✅ 分离,各用最合适的存储。
- ❌ 同步冲突时直接覆盖 → ✅ 保留冲突副本,绝不静默丢数据。
- ❌ 相同文件 / 块存很多份 → ✅ 内容寻址,天然去重。
- ❌ 大文件不做断点续传 → ✅ 分块让续传成为可能,网络一断从断点接着传。
12. 演进路线:MVP → 成长期 → 成熟期
| 阶段 | 规模量级 | 架构长什么样 | 此时该操心什么 |
|---|---|---|---|
| MVP | 起步 | 整文件直传对象存储 + 简单元数据库 | 先把「上传、下载、多设备能看到」跑通 |
| 成长期 | 百万用户 | 分块、增量同步、去重、断点续传、版本历史、回收站 | 带宽与存储成本、同步一致性、冲突 |
| 成熟期 | 海量 / 企业 | 端到端加密、跨区域、海量去重、冷热分层、CDN 分发、协作管控 | 成本、合规、持久性、全球体验 |
13. 可复用要点
- 💡 「分块」是处理大对象的万能钥匙。 断点续传、并行传输、增量同步、去重,几乎都从「先切块」这一步长出来。
- 💡 内容寻址(用哈希当 ID)= 免费的去重。 相同内容自动收敛成一份,Git、容器镜像都靠它。
- 💡 元数据与大对象分离,各用最合适的存储,是存储系统的通用智慧:小而热的强一致,大而冷的堆对象存储。
- 💡 冲突时「保留而非覆盖」:任何多端修改同一资源的系统,都该把「不丢数据」放在「省事」之前。
🎯 随堂检验
- A更高效的压缩算法
- B把文件切成块,只传变化的那几块
- C单纯加大上传带宽
参考原型与延伸阅读
本模板基于以下官方工程博客、真实开源项目与论文整理。
📖 工程博客 / 论文:
- Inside the Magic Pocket (Dropbox Tech Blog) — EB 级 blob 存储:文件切块、跨地域多副本、读写协议。
- Efficient Batched Synchronization in Dropbox-like Cloud Storage (Middleware'13, PDF) — 网盘批量 / 增量同步效率的学术分析。
🔧 开源原型(可直接读代码):
- haiwen/seafile — 自托管文件同步 / 共享,内容寻址的块存储 + 跨库去重 + 增量同步。
📌 一句话记住云存储:它不是「云端的一块硬盘」,而是「一套把大文件切成块、相同块只存一次、只同步变化部分的精算系统」——所有设计都在回答『怎么让文件不丢、随处可得,还尽量少占空间、少耗带宽』。