第 35 章 / 共 57 章 · 约 4 分钟
关键技术:对象存储(S3)
对象存储(Amazon S3、Google Cloud Storage、Azure Blob Storage)用来放文件:图片、视频、备份、日志、模型和数据集。它便宜、几乎无限扩容、极其持久,但只支持整对象的读写,不能在中间修改,也不适合当数据库用。系统设计里的规矩很简单:大文件进对象存储,数据库里只存它的 key 和元数据。
1. 核心模型
- 桶和 key:扁平的命名空间,
bucket/key定位一个对象。key 里的/只是字符,“目录”只是按前缀列出。 - 整对象读写:PUT 写入整个对象,GET 读出(支持按字节范围读),DELETE 删除。没有追加和原地修改,要改就整体重写。
- 一致性:S3 从 2020 年起对 PUT、DELETE 和 LIST 提供强的读后写一致性:写完立刻读就能读到新版本。
- 元数据和版本:对象可以带自定义元数据、开启版本控制,误删可以恢复。
- 预签名 URL:服务端用自己的凭证签出一个有时限的 URL,客户端拿着它直接上传或下载,流量不经过应用服务器。
- 分段上传(multipart):大文件切成多段并行上传,失败的段单独重传,最后合并。
- 存储级别和生命周期:标准、低频访问、归档(Glacier)等级别价格差很多;生命周期规则可以按时间自动转级或删除。
- 事件通知:对象创建后可以触发消息(SQS、SNS、Lambda),启动转码、缩略图、病毒扫描等后续处理。
2. 什么时候用
- 用户上传的媒体:头像、图片、视频、附件。
- 静态资源:前端构建产物、下载文件,前面加 CDN。
- 数据湖和归档:原始日志、事件、数据库备份、机器学习训练集。
- 大批量结果:爬虫抓下来的网页、离线计算的输出,合并成大文件存放。
3. 什么时候不适合
- 小而频繁更新的记录:用户资料、计数器、订单状态应该放数据库;对象存储每次请求都有延迟和费用,也不能部分修改。
- 低延迟随机读写:首字节延迟通常是几十毫秒,不适合当作数据库或文件系统的热数据层。
- 需要文件系统语义:重命名一个“目录”其实是逐个复制再删除;需要锁、追加写、POSIX 语义时,用块存储(EBS)或文件存储(EFS/NFS)。
- 需要和数据库同一个事务:对象存储和数据库之间没有分布式事务,只能靠流程设计保证最终一致(见下文)。
4. 关键限制和数量级
| 维度 | 要记住的事 |
|---|---|
| 对象大小 | 单个对象可以到 TB 级;单次 PUT 最多 5 GB,更大的必须分段上传 |
| 分段上传 | 每段 5 MB 到 5 GB(最后一段可以更小),最多 10000 段 |
| 请求速率 | 每个前缀每秒至少 3500 次写(PUT/COPY/POST/DELETE)和 5500 次读(GET/HEAD),分散到多个前缀可以继续扩展 |
| 持久性 | S3 设计为 11 个 9 的持久性(99.999999999%),跨多个可用区存放 |
| 延迟 | 首字节通常几十毫秒;面向用户的下载要靠 CDN |
| 成本 | 按存储量、请求次数和出网流量计费;出网流量常常是大头,CDN 缓存能明显降低 |
5. 面试中常被追问的点
- 上传流程怎么设计? 客户端先向应用申请上传,应用在数据库里写一条“待上传”记录并返回预签名 URL;客户端直接传到对象存储;对象存储的事件通知(或客户端回调)触发确认和后续处理,记录改成“可用”。详见大文件模式。
- 数据库记录和对象怎么保持一致? 先写元数据再上传,上传失败会留下“待上传”的记录,用超时清理;对象上传了但记录没确认,用生命周期规则清理孤儿对象。
- 怎么控制访问权限? 桶保持私有,由应用签发短时效的下载 URL,或者 CDN 签名 URL / Cookie,不要把桶设为公开。
- 怎么去重? 用内容哈希做 key(内容寻址),相同文件只存一份,元数据里记录引用。
- 大文件下载和断点续传? 用 Range 请求按字节段读取;视频切成小段(HLS/DASH),每段一个对象,经 CDN 分发。
6. 和其他技术的取舍
| 选项 | 适合 | 代价 |
|---|---|---|
| 对象存储 | 海量文件、低成本、高持久 | 只能整对象写,延迟几十毫秒 |
| 块存储(EBS) | 挂在单台机器上的数据库磁盘 | 不能被多台机器共享,容量和价格受限 |
| 文件存储(EFS/NFS) | 需要共享目录和文件系统语义 | 更贵,吞吐受限 |
| 数据库 BLOB 字段 | 很小的文件、需要和记录同一事务 | 拖慢备份和复制,数据库变得臃肿 |
| HDFS | 自建大数据集群 | 运维重,正在被对象存储替代 |
7. 本站案例
- 案例 7:视频流平台:分段上传、转码后的切片和 CDN 分发。
- 案例 4:即时通讯:媒体走预签名 URL,消息里只带
media_ref。 - 案例 8:网络爬虫:抓取的网页合并成大文件存进对象存储,避免数十亿个小文件。