cswork / 系统设计

第 35 章 / 共 57 章 · 约 4 分钟

关键技术:对象存储(S3)

本页目录
  1. 1. 核心模型
  2. 2. 什么时候用
  3. 3. 什么时候不适合
  4. 4. 关键限制和数量级
  5. 5. 面试中常被追问的点
  6. 6. 和其他技术的取舍
  7. 7. 本站案例
  8. 章节测验

对象存储(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. 本站案例

章节测验

5 道选择题
  1. 用户要上传 2 GB 的视频。最合适的上传方式是?
  2. 对象存储和数据库之间没有分布式事务。怎样保证“图片记录”和“图片文件”最终一致?
  3. 以下哪类数据最不适合放在对象存储里?
  4. 私有图片要让登录用户在网页里查看,但不能公开给所有人。常用做法是?
  5. 用户反复上传同一个文件,想只存一份。最简单的设计是?

章节讨论

正在加载讨论…