Skip to content

文件存储与对象存储

前言

用户上传了一张头像,你把它存在服务器的 /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. 存储类型对比:块、文件、对象

计算机世界有三种主要的存储方式,它们解决不同层次的问题。

存储类型对比
点击查看不同存储方式的特点
🧱
块存储
📁
文件存储
☁️
对象存储
对象存储
通过 HTTP API 存取文件(对象),每个对象有唯一 Key。扁平结构,无目录层级。容量几乎无限,成本最低,是互联网应用的首选。
访问方式
HTTP/HTTPS RESTful API(PUT/GET/DELETE)
典型场景
图片、视频、备份、静态网站托管、数据湖
代表产品
AWS S3、阿里云 OSS、MinIO、Cloudflare R2
扩展性
近乎无限扩展,自动分布式存储
维度块存储文件存储对象存储
数据单位固定大小的块文件 + 目录对象(Key-Value)
访问协议iSCSI/FCNFS/SMBHTTP 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-prodcompany-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. 文件上传方案:谁来传文件?

文件上传有两种主流方案:服务端中转和客户端直传。对于大多数场景,客户端直传是更优的选择。

文件上传方式对比
点击切换查看两种上传方式的流程差异
1
客户端 → 服务器
用户选择文件,上传到你的后端服务器
大文件会占用服务器带宽和内存
2
服务器接收文件
后端将文件暂存到本地磁盘或内存
可能触发 Nginx 的 body size 限制
3
服务器 → OSS
后端再将文件转发到对象存储
文件传输了两次,效率低
4
OSS 返回 URL
对象存储返回文件的访问地址
5
服务器 → 客户端
后端将文件 URL 返回给前端

客户端直传的优势

  1. 节省服务器带宽:文件不经过你的服务器,直接到 OSS
  2. 避免超时:大文件上传不会触发 Nginx/网关的超时限制
  3. 降低服务器负载:服务器只需要签发凭证,不需要处理文件流
  4. 支持断点续传:OSS 原生支持分片上传,前端可以实现断点续传

实现步骤:前端请求后端获取 Pre-signed URL → 前端用这个 URL 直接上传到 OSS → OSS 回调通知后端


4. CDN 加速:让全球用户都快

当你的用户遍布全球时,从单一源站下载文件会很慢。CDN(Content Delivery Network)通过在全球部署边缘节点,将文件缓存到离用户最近的节点,大幅降低访问延迟。

CDN 加速原理
对比有无 CDN 时的文件访问路径
👤
北京用户
5ms
北京 CDN 节点
缓存命中
缓存未命中时回源
🏢
源站(美西 S3)
首字节时间 (TTFB)
~30ms
下载 1MB 图片
~50ms
CDN 概念说明
边缘节点分布在全球各地的缓存服务器
回源边缘节点没有缓存时,向源站请求文件
缓存命中率请求被边缘节点直接响应的比例,越高越好
TTL缓存有效期,过期后需要重新回源
缓存刷新主动清除边缘节点的缓存,让新文件生效

CDN 最佳实践

  • 文件名加 hashlogo.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
服务端加密敏感文件开启 SSESSE-S3 或 SSE-KMS

总结

文件存储是每个 Web 应用都会遇到的基础问题。对象存储以其无限容量、低成本、高可用的特性,成为了互联网应用的标准选择。

回顾本章的关键要点:

  1. 三种存储类型:块存储给数据库、文件存储给共享、对象存储给用户文件
  2. 对象存储模型:Bucket + Key + Object,扁平结构,HTTP API 访问
  3. 客户端直传:Pre-signed URL 方案,文件不经过服务器,高效省资源
  4. CDN 加速:边缘节点缓存 + 文件名 hash,让全球用户都快
  5. 安全与管理:权限最小化、生命周期规则、服务端加密

延伸阅读