# 云存储 / 网盘 架构模板 > **代表产品**: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 个变化的块,其余原封不动 ── 这就是「改一点只传一点」,而不是重传 1GB ``` ## 7. 数据模型与存储选择 核心实体:`文件 / 文件夹(元数据:路径、版本、块清单)`;`块(内容哈希 → 数据)`;`用户 / 配额`。 | 数据 | 存储类型 | 为什么 | |---|---|---| | 目录树 / 版本 / 块清单 | 关系型(强一致) | 频繁查改、要事务、是「文件结构」的真相 | | 内容块 | 对象存储(内容寻址) | 海量、不可变、按哈希取、天然去重 | | 冷数据 / 老版本 | 廉价归档存储 | 很少访问,放冷存储省钱 | | 同步状态 | KV / 内存 | 高频、设备级 | > 教学点:**用「内容哈希」当块的 ID**,相同内容自然得到相同 ID、只存一份——这就是去重。Git 存对象、容器镜像分层,用的都是这套「内容寻址」。 ## 8. 关键架构决策与权衡 ⭐ **决策 1:整文件存储,还是分块存储?(一切能力的源头)⭐** - 整文件:简单,但改一个字要重传整个文件、传一半断了要重来、相同文件存很多份。 - 分块:把文件切成固定 / 可变大小的块。 - **取向**:必然分块。**断点续传、增量同步、去重、并行传输——全是分块的副产品。** 代价是要维护「文件 → 块清单」的映射和块的生命周期。 **决策 2:块用「内容寻址」(哈希当 ID)⭐** - 用随机 ID / 路径当块标识:相同内容会被当成不同块,存很多份。 - 用内容哈希当块 ID:相同内容 → 相同哈希 → 自动只存一份。 - **取向**:内容寻址。它让**去重变成存储的自然属性**,而不用额外比对。代价是哈希计算开销、和极小概率哈希碰撞的处理。 **决策 3:元数据和内容,分开存 ⭐** - 混在一起:大文件和小元数据用同一种存储,两头都不讨好。 - 分离:元数据(小、强一致、频繁)用关系型;内容(大、不变、海量)用对象存储。 - **取向**:必分。**这是「按数据的访问形态选存储」的标准范例。** **决策 4:多设备离线改同一文件,冲突怎么办?** - 后同步的覆盖先的:简单,但**会丢数据**。 - 检测到冲突时**保留两个版本**(生成「冲突副本」),交给用户决定。 - **取向**:宁可留冲突副本,也不静默覆盖。**和 [协同文档](../collaborative-doc/README.md) 一样:保留,而非覆盖。** ## 9. 规模化与瓶颈 - **第一个瓶颈:元数据服务随用户和文件数膨胀。** → 破解:按用户分片(一个用户的文件树落在一处,查询不跨片)。 - **第二个瓶颈:内容存储规模。** → 破解:对象存储天生近乎无限扩展;配合去重和冷热分层压成本。 - **第三个瓶颈:同步通知的扇出**(一个改动要通知用户的所有设备)。→ 破解:发布 - 订阅 + 长连接,见 [通知系统模板](../notification-system/README.md)。 - **第四个瓶颈:热点文件被海量分享下载。** → 破解:CDN 缓存分发,见 [视频流媒体模板](../video-streaming/README.md)。 ## 10. 安全与合规要点 - **加密**:传输加密 + 静态加密是底线;高敏场景上**端到端加密**(但 E2EE 下服务端做不了去重和云端预览,是真实取舍)。 - **共享权限**:链接可见范围、过期、密码、只读 / 可编辑。 - **数据隔离与驻留**:多租户隔离;企业 / 监管可能要求数据存在特定地域。 - **滥用治理**:防止被用来存 / 传违法内容,需要合规检测机制。 ## 11. 常见误区 / 反模式 - ❌ **整文件传输,改一个字重传整个文件** → ✅ 分块 + 增量,只传变化的块。 - ❌ **元数据和内容混在一种存储里** → ✅ 分离,各用最合适的存储。 - ❌ **同步冲突时直接覆盖** → ✅ 保留冲突副本,绝不静默丢数据。 - ❌ **相同文件 / 块存很多份** → ✅ 内容寻址,天然去重。 - ❌ **大文件不做断点续传** → ✅ 分块让续传成为可能,网络一断从断点接着传。 ## 12. 演进路线:MVP → 成长期 → 成熟期 | 阶段 | 规模量级 | 架构长什么样 | 此时该操心什么 | |---|---|---|---| | **MVP** | 起步 | 整文件直传对象存储 + 简单元数据库 | 先把「上传、下载、多设备能看到」跑通 | | **成长期** | 百万用户 | 分块、增量同步、去重、断点续传、版本历史、回收站 | 带宽与存储成本、同步一致性、冲突 | | **成熟期** | 海量 / 企业 | 端到端加密、跨区域、海量去重、冷热分层、CDN 分发、协作管控 | 成本、合规、持久性、全球体验 | ## 13. 可复用要点 - 💡 **「分块」是处理大对象的万能钥匙。** 断点续传、并行传输、增量同步、去重,几乎都从「先切块」这一步长出来。 - 💡 **内容寻址(用哈希当 ID)= 免费的去重。** 相同内容自动收敛成一份,Git、容器镜像都靠它。 - 💡 **元数据与大对象分离,各用最合适的存储**,是存储系统的通用智慧:小而热的强一致,大而冷的堆对象存储。 - 💡 **冲突时「保留而非覆盖」**:任何多端修改同一资源的系统,都该把「不丢数据」放在「省事」之前。 ## 🎯 随堂检验 --- ## 参考原型与延伸阅读 > 本模板基于以下**官方工程博客**、**真实开源项目**与**论文**整理。 **📖 工程博客 / 论文:** - [Inside the Magic Pocket (Dropbox Tech Blog)](https://dropbox.tech/infrastructure/inside-the-magic-pocket) — EB 级 blob 存储:文件切块、跨地域多副本、读写协议。 - [Efficient Batched Synchronization in Dropbox-like Cloud Storage (Middleware'13, PDF)](https://sites.cs.ucsb.edu/~ravenben/publications/pdf/dropbox-middleware13.pdf) — 网盘批量 / 增量同步效率的学术分析。 **🔧 开源原型(可直接读代码):** - [haiwen/seafile](https://github.com/haiwen/seafile) — 自托管文件同步 / 共享,内容寻址的块存储 + 跨库去重 + 增量同步。 --- > 📌 一句话记住云存储:**它不是「云端的一块硬盘」,而是「一套把大文件切成块、相同块只存一次、只同步变化部分的精算系统」——所有设计都在回答『怎么让文件不丢、随处可得,还尽量少占空间、少耗带宽』。**