尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

system-design-notes:邮件附件如何存储?本地目录存储的目录结构设计详解

system-design-notes:邮件附件如何存储?本地目录存储的目录结构设计详解 system-design-notes邮件附件如何存储本地目录存储的目录结构设计详解【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insiders Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notessystem-design-notes是经典系统设计面试书籍System Design Interview: An Insiders Guide的配套笔记仓库用 28 个章节拆解了从缓存扩展到分布式邮件服务的真实系统设计。本章聚焦第 23 章 Distributed Email Service——设计一个类似 Gmail 的分布式邮件系统其中「邮件附件如何存储」是一个极具代表性的问题从小型邮件服务器上的本地目录存储Maildir 目录结构设计到大规模场景下附件分离到对象存储的演进本文带你一次看懂。一、传统邮件服务器一封邮件就是一个文件在设计分布式方案之前先理解传统邮件服务器是怎么存邮件的。传统架构下Alice 通过 SMTP 发送邮件Outlook 服务器查询 DNS 的 MX 记录把邮件投递给 Gmail 服务器Bob 再通过 IMAP/POP 拉取邮件![传统邮件服务器与本地文件存储架构](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/traditional-mail-server.png?utm_sourcegitcode_repo_files)这种模式在用户量有限时运行良好。其核心存储策略非常朴素每封邮件都是本地文件系统上的一个独立文件。当规模增长后磁盘 I/O 会成为瓶颈而且单台服务器一旦宕机所有数据都面临丢失风险无法满足高可用与可靠性要求。二、Maildir 目录结构设计详解那么每封邮件一个文件具体是怎么组织目录的业界事实标准是Maildir 方案。仓库中的这张图展示了它的典型结构![Maildir 本地目录存储结构设计每封邮件是独立文件](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/local-dir-storage.png?utm_sourcegitcode_repo_files)以 Linux 为例目录结构如下home/ ├── user1/ │ └── Maildir/ │ ├── cur/ # 当前已读/处理中的邮件 │ ├── new/ # 新到达、尚未处理的邮件 │ └── tmp/ # 正在写入中的临时邮件 └── user2/ └── Maildir/ ├── cur/ ├── new/ └── tmp/1️⃣ cur、new、tmp 三个子目录各自做什么目录作用new新邮件先落在这里。邮箱程序轮询时从这里发现新邮件读完后文件被移走cur表示当前已交付的邮件集合。客户端正在查看、已标记已读或保留的邮件都在这里tmp临时缓冲区。新邮件先完整写入 tmp写完后通过一次原子 rename 移动到 new2️⃣ 为什么 tmp 目录是 Maildir 的精髓原子性写入邮件写入过程分两步——先写入tmp再用rename()原子地移动到new。rename 在同一文件系统上是原子操作因此任何读者看到的要么是完整的旧状态要么是完整的邮件永远不会读到写了一半的邮件。无锁设计所有状态变化都通过文件在目录间移动来表达目录里有什么文件就是什么状态。不需要文件锁天然支持多进程并发读。故障恢复简单如果服务器在写入时崩溃tmp中残留的不完整文件在重启时直接清理即可不会污染new和cur。三、本地目录存储在大规模下的瓶颈回到 README.md 中的估算10 亿用户、每天 1000 万封邮件、约 20% 邮件带平均 500KB 的附件一年附件存储量就达 1460PB——本地磁盘目录显然撑不住。本地目录存储的三大硬伤⚠️磁盘 I/O 瓶颈海量小文件随机读写IOPS 吃紧⚠️单点故障磁盘损坏或服务器宕机即数据丢失⚠️无法水平扩展本地目录天然绑定单台服务器四、演进方向附件元数据与文件本体分离所以分布式邮件服务中附件存储发生了关键转变——元数据进数据库文件本体进对象存储如 Amazon S3![分布式邮件系统高层架构附件存储在对象存储](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/high-level-architecture.png?utm_sourcegitcode_repo_files)数据库中的附件表非常精简只保存文件名和对象存储 URL的映射而不是附件本体![邮件附件表结构设计attachments 表按 email_id 与 filename 索引](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/attachments.png?utm_sourcegitcode_repo_files)表字段说明emails_by_userattachments:LISTfilename\|size邮件行内只记录附件的文件名和大小attachmentsemail_id (TIMEUUID), filename (K), url文件名作为主键url 指向对象存储这样设计的好处✅ 读取邮件列表时不触碰大文件列表页响应快✅ 附件按需从对象存储拉取可独立水平扩展✅ 补充细节邮件附件在网络传输时是base64 编码的主流邮件服务通常限制在 25MB 以内 进阶优化点可作为系统设计加分项去重。不同的用户多次发送同一个附件时可以用内容哈希如 SHA-256判重只存储一份进一步节省对象存储成本。五、小结一张图看懂附件存储的演进阶段附件存储位置代表适合规模传统方案本地 Maildir 目录new/cur/tmp传统邮件服务器单服务器、有限用户分布式方案元数据在数据库 本体在对象存储S3Gmail 类系统十亿级用户、PB 级存储Maildir 的 cur/new/tmp 三目录结构是单机邮件存储的经典设计理解它的原子写入和无锁思想而附件与元数据分离、大文件下沉对象存储则是任何大规模文件/附件类系统网盘、云相册通用的设计模式。想深入完整的设计推导发送流程、收件流程、搜索、多数据中心容灾可阅读 23. Distributed Email Service 章节 原文。【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insiders Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表