文件存儲與對象存儲
前言
用户上傳了一张頭像,你把它存在服務器的 /uploads 目錄下——然後服務器磁盘满了,或者你加了第二台服務器,用户發現頭像時有時无。 文件存儲看似简單,但在分布式環境下却是一个需要認真對待的架構問题。對象存儲就是互聯網時代解决這个問题的標準答案。
這篇文章會带你學什么?
學完這章後,你将獲得:
- 存儲類型認知:理解塊存儲、文件存儲、對象存儲的區別和適用場景
- 對象存儲核心概念:掌握 Bucket、Object、Key、Pre-signed URL 等核心概念
- 上傳方案設計:學會客户端直傳 vs 服務端中轉的方案選型
- CDN 加速原理:理解 CDN 如何加速静態资源的全球分發
- 最佳實踐:掌握文件命名、權限控制、生命周期管理等實戰技巧
| 章節 | 內容 | 核心概念 |
|---|---|---|
| 第 1 章 | 存儲類型對比 | 塊存儲、文件存儲、對象存儲 |
| 第 2 章 | 對象存儲核心概念 | Bucket、Object、Key、元數據 |
| 第 3 章 | 文件上傳方案 | 客户端直傳、Pre-signed URL |
| 第 4 章 | CDN 加速 | 邊缘節點、緩存策略、回源 |
| 第 5 章 | 最佳實踐 | 命名規范、權限、生命周期 |
0. 全景图:為什么不能把文件存在服務器本地?
刚開始做项目時,把用户上傳的文件存在服務器本地目錄是最直觉的做法。但隨着项目發展,你會遇到一系列問题:
- 磁盘空間有限:服務器磁盘總會满,擴容麻烦
- 多服務器不共享:负載均衡後,用户請求可能打到不同服務器,文件找不到
- 没有備份:服務器挂了,文件就丟了
- 没有 CDN:全球用户访問同一台服務器,速度慢
對象存儲的核心价值
對象存儲(如 AWS S3、阿裡云 OSS)解决了所有這些問题:容量无限、全球可访問、自動備份、天然支持 CDN。它已經成為互聯網應用存儲文件的事實標準。
1. 存儲類型對比:塊、文件、對象
計算機世界有三種主要的存儲方式,它们解决不同層次的問题。
| 維度 | 塊存儲 | 文件存儲 | 對象存儲 |
|---|---|---|---|
| 數據單位 | 固定大小的塊 | 文件 + 目錄 | 對象(Key-Value) |
| 访問協议 | iSCSI/FC | NFS/SMB | HTTP REST API |
| 性能 | 最高(毫秒级) | 中等 | 較低(但够用) |
| 擴展性 | 有限 | 中等 | 近乎无限 |
| 成本 | 最高 | 中等 | 最低 |
| 典型場景 | 數據庫 | 共享文件 | 图片/视频/備份 |
简單記忆
- 塊存儲像硬盘——给數據庫用
- 文件存儲像網絡共享文件夹——给多台服務器共享配置用
- 對象存儲像網盘——给用户上傳的图片、视频用
2. 對象存儲核心概念
對象存儲的數據模型非常简單:Bucket(桶) 是容器,Object(對象) 是文件,每个對象通過唯一的 Key(鍵) 來標識。
my-app-bucket/ ← Bucket(桶)
├── avatars/user-123.jpg ← Object Key
├── avatars/user-456.png ← Object Key
├── reports/2024/q1-report.pdf ← Object Key("目錄"只是 Key 的前缀)
└── uploads/temp/file.zip ← Object Key| 概念 | 說明 | 示例 |
|---|---|---|
| Bucket | 存儲容器,全局唯一命名 | my-app-prod、company-assets |
| Object | 存儲的文件本體 + 元數據 | 一张图片、一个 PDF |
| Key | 對象的唯一標識符 | avatars/user-123.jpg |
| 元數據 | 對象的附加信息 | Content-Type、自定義標簽 |
| ACL | 访問控制列表 | public-read、private |
| Pre-signed URL | 臨時授權访問鏈接 | 有效期 15 分鐘的上傳/下載鏈接 |
對象存儲没有真正的"目錄"
avatars/user-123.jpg 中的 avatars/ 不是目錄,只是 Key 的前缀。對象存儲是扁平結構,所有對象在同一層级。控制台顯示的"文件夹"只是按前缀分組的视觉效果。
3. 文件上傳方案:誰來傳文件?
文件上傳有兩種主流方案:服務端中轉和客户端直傳。對于大多數場景,客户端直傳是更優的選择。
客户端直傳的優勢
- 節省服務器带宽:文件不經過你的服務器,直接到 OSS
- 避免超時:大文件上傳不會触發 Nginx/網關的超時限制
- 降低服務器负載:服務器只需要簽發凭證,不需要處理文件流
- 支持断點續傳:OSS 原生支持分片上傳,前端可以實現断點續傳
實現步骤:前端請求後端獲取 Pre-signed URL → 前端用這个 URL 直接上傳到 OSS → OSS 回調通知後端
4. CDN 加速:讓全球用户都快
当你的用户遍布全球時,從單一源站下載文件會很慢。CDN(Content Delivery Network)通過在全球部署邊缘節點,将文件緩存到離用户最近的節點,大幅降低访問延遲。
| CDN 概念 | 說明 |
|---|---|
| 邊缘節點 | 分布在全球各地的緩存服務器 |
| 回源 | 邊缘節點没有緩存時,向源站請求文件 |
| 緩存命中率 | 請求被邊缘節點直接響應的比例,越高越好 |
| TTL | 緩存有效期,過期後需要重新回源 |
| 緩存刷新 | 主動清除邊缘節點的緩存,讓新文件生效 |
CDN 最佳實踐
- 文件名加 hash:
logo.a3f2b1.png而不是logo.png,這样更新文件時不需要刷新緩存 - 設置合理的 TTL:静態资源(JS/CSS/图片)設長 TTL(1年),HTML 設短 TTL(5分鐘)
- 開启 Gzip/Brotli 压缩:文本類资源压缩後體积减少 60-80%
5. 最佳實踐
| 實踐 | 說明 | 示例 |
|---|---|---|
| Key 命名規范 | 用有意義的前缀組织文件 | {type}/{date}/{uuid}.{ext} |
| 避免热點 Key | 不要用遞增數字開頭 | 用 UUID 或 hash 前缀 |
| 權限最小化 | Bucket 默認 private | 只對需要公開的文件設置 public-read |
| 生命周期規则 | 自動清理過期文件 | 臨時文件 7 天後自動删除 |
| 跨域配置 | 前端直傳需要配置 CORS | 允许你的域名 PUT/POST |
| 服務端加密 | 敏感文件開启 SSE | SSE-S3 或 SSE-KMS |
總結
文件存儲是每个 Web 應用都會遇到的基础問题。對象存儲以其无限容量、低成本、高可用的特性,成為了互聯網應用的標準選择。
回顧本章的關鍵要點:
- 三種存儲類型:塊存儲给數據庫、文件存儲给共享、對象存儲给用户文件
- 對象存儲模型:Bucket + Key + Object,扁平結構,HTTP API 访問
- 客户端直傳:Pre-signed URL 方案,文件不經過服務器,高效省资源
- CDN 加速:邊缘節點緩存 + 文件名 hash,讓全球用户都快
- 安全與管理:權限最小化、生命周期規则、服務端加密
延伸阅讀
- AWS S3 開發者指南 - 對象存儲的標杆文檔
- 阿裡云 OSS 最佳實踐 - 国內最常用的對象存儲
- MinIO 文檔 - 開源的 S3 兼容對象存儲
- Cloudflare R2 - 零出口費用的對象存儲
- Pre-signed URL 詳解 - 客户端直傳的核心機制