system-design-notes第23章:设计分布式邮件服务(类Gmail)完整指南 system-design-notes第23章设计分布式邮件服务类Gmail完整指南【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insiders Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes本文基于system-design-notes第23章带你完整走一遍如何设计一个类似Gmail的分布式邮件服务从容量估算、高层架构、邮件收发流程到元数据数据库与全文搜索帮助新手快速掌握这个经典的系统设计面试题。 为什么设计类Gmail邮件系统2020年 Gmail 拥有18亿活跃用户Outlook 也有4亿用户邮件服务是典型的大规模分布式系统设计问题。核心功能设计范围 发送邮件 / 接收邮件 获取与过滤邮件 全文搜索️ 反垃圾邮件保护非功能性需求需求关键点可靠性绝不能丢失用户的邮件可用性用复制防止单点故障容忍部分失败可扩展性用户增长时系统能弹性扩展灵活性选用 HTTP 而非 SMTP 等协议便于扩展新功能 第1步明确需求与容量估算开始设计前先做背级估算back-of-the-envelope estimation指标假设估算结果用户规模10亿用户—发送负载每人每天发 10 封约10万封/秒元数据存储每人每天收 40 封每封约 50KB 元数据约730PB/年附件20% 的邮件带 500KB 附件约1460PB/年 存储量每年超过 2PB这正是必须分布式的根本原因。估算方法可参考 02. Back Of the Envelope Estimation。️ 第2步高层架构设计从传统邮件服务器说起先看传统邮件服务器如何工作Alice 通过SMTP把邮件发到 Outlook 服务器Outlook 服务器查询DNS 的 MX 记录找到 Gmail 的邮件服务器并转发Bob 再用IMAP/POP从本地服务器取信。![传统邮件服务器架构图SMTP发送、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)跨服务器发邮件前需先查询 MX 记录以下是查询 gmail.com 的 MX 记录示例![通过nslookup查询Gmail邮件交换器MX记录的终端示例](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/dns-lookup.png?utm_sourcegitcode_repo_files)传统架构中每封邮件都是本地文件系统里的一个独立文件![传统邮件在本地目录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)随着规模增长磁盘 I/O 成为瓶颈且磁盘损坏、服务器宕机无法满足高可用与可靠性要求。分布式邮件服务器架构分布式邮件服务器仍支持 IMAP/POP 与 SMTP但对 Web 端则提供HTTP 上的 RESTful APIPOST /v1/messages— 发送邮件To、Cc、BccGET /v1/folders— 获取全部文件夹GET /v1/folders/{:folder_id}/messages— 分页获取文件夹中的邮件GET /v1/messages/{:message_id}— 获取邮件详情高层架构包含 7 个部分![分布式邮件服务高层架构Webmail、Web服务器、实时服务器与存储层元数据、附件、缓存、搜索](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/19. Distributed Message Queue/images/high-level-architecture.png?utm_sourcegitcode_repo_files)组件职责Webmail用户通过浏览器收发邮件Web Servers登录、注册、用户画像等对外服务Real-time Servers实时推送新邮件WebSocket旧浏览器降级长轮询Metadata DB主题、正文、发件人等元数据Attachment Store对象存储类 S3存大文件Distributed Cache用 Redis 缓存最近邮件改善体验Search Store分布式文档库支持全文搜索设计原文见 Step 2: High-Level Design。 邮件发送流程详解![分布式邮件服务发送流程图负载均衡、消息队列、SMTP出站工作器与存储层协同](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/email-sending-flow.png?utm_sourcegitcode_repo_files)流程拆解用户写完邮件点发送请求先到负载均衡器负载均衡器做限流再路由到某台 Web 服务器Web 服务器做基础校验如邮件大小发件人与收件人同域则短路直发先做垃圾检查校验通过 → 写入发送消息队列附件只引用对象存储的地址失败 → 进错误队列SMTP 出站工作器拉取消息执行垃圾邮件/病毒检查后路由到目标邮件服务器邮件存入已发送文件夹⚠️ 务必监控发送队列长度接收方服务器不可用时用指数退避重试消费者吞吐不足时扩容消费者。 邮件接收流程详解![分布式邮件服务接收流程图SMTP服务器准入策略、垃圾检查与实时推送](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/email-receiving-flkow.png?utm_sourcegitcode_repo_files)入站邮件先到SMTP 负载均衡器SMTP 服务器执行邮件接收策略无效邮件直接丢弃附件过大时转存对象存储S3邮件处理工作器做初步检查垃圾、病毒后把数据写入存储层元数据库、搜索库、对象存储、缓存在线用户通过 WebSocket 实时推送收信离线用户上线后走 HTTP API 拉取 第3步元数据数据库设计邮件元数据的特征头部小、访问频繁正文可大可小但通常只读一次大多数操作孤立于单个用户取信、标已读、搜索用户通常只读最近的邮件数据丢失不可接受可靠性要求最高在 Gmail 这个量级数据库通常自研以降低 IOPS。现有方案都有短板选项短板关系型数据库为小数据块优化不适合大正文列分布式对象存储适合备份但搜索/标记已读效率低NoSQL如 BigTableGmail 所用方案未开源关键设计点用user_id作为分区键一个用户的数据落在同一分片主键 分区键数据分布 聚类键数据排序email_id使用TimeUUID天然按创建时间排序核心表结构如下K 分区键C↓ 聚类键降序![emails_by_folder邮件表结构user_id、folder_id分区键与TimeUUID降序排序](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/emails-table.png?utm_sourcegitcode_repo_files)附件单独建表以文件名为键正文中只存对象存储的引用![emails_by_user与attachments表结构附件独立存储并引用URL](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/attachments.png?utm_sourcegitcode_repo_files)已读/未读过滤在 NoSQL 中是痛点禁止在非键字段上过滤解法是把邮件表反范式化为已读/未读两张表![read_emails与unread_emails两张反范式化邮件表结构](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/read-unread-emails.png?utm_sourcegitcode_repo_files)一致性权衡上用可用性换一致性邮件不能丢是硬性要求故障切换或网络分区时同步操作会短暂不可用。 邮件全文搜索怎么做与 Google 搜索不同邮件搜索是用户本地的Google 搜索邮件搜索范围整个互联网用户自己的邮箱排序按相关性按时间、日期等属性准确性建索引耗时结果非实时必须快且结果准确邮件搜索写多读少每次收/发/删都要重建索引但用户很少用搜索功能。两种方案方案 AElasticsearch 集群推荐![Elasticsearch邮件搜索架构收删邮件经Kafka异步重建索引搜索同步查询](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/elasticsearch.png?utm_sourcegitcode_repo_files)变更操作发/收/删经Kafka 异步触发重建索引与服务解耦实际搜索查询是同步的同样用user_id做分区键把同一用户的数据分到同一节点方案 B自研搜索引擎用 **LSM 树Log-Structured Merge-Tree**组织磁盘索引写路径只做顺序写优化——Cassandra、BigTable、RocksDB 都采用这一技术数据先在内存攒批达到阈值后逐层合并到磁盘![LSM树分层合并结构Level 0内存层逐级合并至Level 4磁盘层](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/lsm-tree.png?utm_sourcegitcode_repo_files)两方案取舍维度Elasticsearch自研搜索引擎扩展性够用可为邮件场景精调扩展上限更高维护成本独立服务需单独维护可与存储引擎合一开发成本现成方案需大量工程量 投递性、扩展性与高可用**邮件投递性deliverability**是个隐形难题新搭的邮件服务器直接发信大概率进垃圾箱。常用手段 使用专用 IP建立信誉预热 IP2~6 周积累良好声誉️分类邮件——营销邮件不与重要邮件共用发送服务器️ 用SPF、DKIM等认证技术反钓鱼 快速封禁垃圾用户并与 ISP 建立反馈循环跟踪投诉率扩展性单个用户的操作互不干扰多数组件可独立水平扩展。高可用多数据中心部署 主从故障切换![多数据中心部署美国与欧洲数据中心相互复制主中心故障时用户切到从中心](https://raw.gitcode.com/GitHub_Trending/sy/system-design-notes/raw/9d8388721e7231442763ad37398b8d82224aa68f/23. Distributed Email Service/images/multi-dc-example.png?utm_sourcegitcode_repo_files) 总结与延伸思考本章分布式邮件服务设计可归纳为 5 点架构Web / Real-time 双服务器 元数据、附件、缓存、搜索四层存储异步解耦收发流程走消息队列并监控队列做退避与扩容存储user_id分区、TimeUUID 排序、已读/未读反范式化、一致性优先搜索Elasticsearch 集群 Kafka 异步建索引可用多数据中心复制 故障切换面试中还可延伸容错节点故障如何处理、合规GDPR 下个人数据存储、安全邮件加密、反钓鱼、优化不同用户重复发送的相同附件去重。 本章资料23. Distributed Email Service/README.md附件对象存储与 24. S3-like Object Storage 的设计思路相通建议对照阅读。【免费下载链接】system-design-notesNotes of the book System Desgin Interview - An Insiders Guide项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-notes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考