系统设计 22:限流器的原子计数与全局配额
“每个用户每秒允许十次”还不足以实现限流。十次是自然秒内计数、任意一秒窗口,还是长期每秒十次并允许短时突发?配额由一个实例独占,还是十个网关各发十个令牌?请求到达时间、计数位置和原子边界不同,允许数量就不同。 本篇把 API 限流设计成明确的资源分配协议:令牌桶容量为 B、补充速率为 r,请求花费一个令牌;多个入口共享同一逻辑配额。目标是限制成本较高的查询,不承担账户余额、座位库存等不可超发资源的最终正确性。所有容量数字为教学假设,实验在真实 SQLite 上验证共享状态事务,不声称验证了 Redis Lua。 限流键也是授权边界 网关先鉴权,再用稳定的租户 ID 和 API 类别组成配额键。直接信任客户端提交的 user_id 会允许换键绕过限流;只按 IP 则可能惩罚共享出口的公司或学校。未认证请求可以用 IP 做粗粒度保护,但不能由此推导认证用户公平性。 限流调用可表述为 acquire(tenant, route_class, cost, request_id),返回 allowed, retry_after, remaining。业务 API 被拒绝时返回 429;R...
系统设计 21:输入联想的前缀索引与结果新鲜度
输入 ca 后返回 car,不是一次缩小版的全文搜索。候选集合必须满足前缀约束,排序由热度决定,而删除、敏感词和租户权限还会改变哪些结果允许展示。把前缀到十个字符串的映射放进缓存,只解决了读取成本,没有解决热度变更后谁刷新映射、撤销后谁阻止旧结果返回。 本篇承接第 20 篇的索引新鲜度问题,设计一个公共词库的输入联想服务。个性化推荐、中文拼音纠错和训练排序模型不在范围内。这里所有负载与时限都是教学假设,实验使用自建前缀树和预计算表,不代表 Elasticsearch 的实际性能。 请求契约先于索引选型 业务允许词库管理员创建、提权和删除候选词;用户只能读取通过审核的词。查询返回至多十项,按热度降序、规范化词条升序打破并列。每条结果带稳定的 term_id,前端不能把字符串当永久身份。目标设为查询入口到响应 p99 小于 50 ms,普通热度一分钟内生效,紧急删除在删除提交后的新请求中不可见。这两个新鲜度目标不能混成一个缓存 TTL。 GET /suggest?prefix=ca&limit=10&locale=en 返回 generation 与结果列表。服务对...
系统设计 20:社交内容搜索的增量索引与新鲜度
一条动态先写下 blue bird,后来改成 green bird,最后被删除。搜索端如果只追加“新增词项”,blue 和 green 可能同时搜到同一条;即使正确删除了词项,迟到的旧编辑事件还能把已删内容重新放回结果。这是 Twitter Search 类型题目里比“用什么倒排索引”更先要回答的问题:一次修改怎样替换旧词集,重放为什么不能覆盖新版本,以及用户究竟在等哪个“可搜索”时刻。 本文设计公共短文本搜索,不声称是 Twitter 的真实架构;第 19 篇信息流候选排序与权限撤销处理旧候选的读时安全门禁,下一篇输入联想则查询词条前缀而不是全文。分片与排名是教学设计;实验的延迟是本地 SQLite FTS5 查询观测,不代表分布式搜索引擎性能。 “发布成功”和“能搜到”分开定义 允许发帖、编辑、删除、按单词查询公开内容;搜索结果不得混入另一个租户或私密帖子。帖子权威数据与索引分离,发帖成功表示权威状态及可重放变更记录已持久接受,不等于已经刷新可搜索索引。编辑在索引里必须替换旧版本的词项,删除必须同时撤掉词项并保留能挡住旧事件的墓碑。对任一 post_id,索引应用的版本只能...
系统设计 19:信息流候选排序与权限撤销
早上预先给读者生成的候选列表,下午依然排着一条帖子;但帖子已经被删除,读者也不再关注另一条帖子的作者。只把新帖子送进新的候选列表,无法修复早上的旧列表。信息流的难处不是给一条帖子算出多少分,而是派生列表中的旧引用何时可以展示。 本篇的问题是 Facebook Newsfeed 类型的关注信息流,而不是介绍某家公司实际采用的架构。上一章时间线的推拉与热点作者只按时间归并;这里在候选生成后加入确定性排序,并让删除与权限变更越过旧候选生效。以下规模、时限和特征分数均为教学假设;实验使用真实 SQLite 内存数据库和固定候选列表,不是机器学习训练或线上排名效果。 先界定什么不能错 用户关注作者,作者发布公开或仅关注者可见的内容。GET /feed 返回当前用户能看的最多 20 条帖子,并给出继续读取的游标。作者能删除帖子、将可见范围收紧;读者取消关注后,不应通过旧收件箱继续读到仅关注者可见的帖子。候选可以延迟抵达,排序可以不是全局最优,但已经完成撤销的请求,不得靠旧候选继续泄露内容。 这个承诺要写清边界:本设计只保证撤销接口成功返回之后开始的新读请求,对当前权威状态做完检查才返回;撤...
系统设计 18:微博时间线:同一负载下比较推、拉与混合
一个普通作者只有十个关注者,一个热点作者有一千个关注者。如果两人各发两条动态,全量写入扇出会产生 2020 份收件箱引用;如果只有五个人打开首页,其中大量预写永远不会被读到。时间线设计首先比较写时做多少工作与读时做多少工作,而不是先决定使用哪种缓存。 Twitter 在这里是公开发布和关注时间线的题型。基础时间线按发布时间倒序,不加入机器学习排序;排序信息流留给下一篇。本文使用固定关注图比较策略,不声称这些数字来自真实社交产品。 候选 SLO 是已授权用户取首页 20 条在五分钟窗口内 p99 小于 200 ms;99% 的普通作者帖子在三十秒内进入已关注读者的候选集。热点作者靠读时拉取,延迟单独定义;本次整数操作数模型没有真实时钟、队列和用户分布,不能把该目标写成已经达标。 发布与时间线不是同一份事实 POST /posts 提交正文与客户端幂等键,写入 posts(post_id, author_id, created_seq, body, version, deleted);PUT /following/{author_id} 和 DELETE 修改关...
系统设计 17:即时通信:连接恢复以后,消息怎样补齐
发送按钮变成勾号之前,究竟发生了哪件事:网关收到字节,服务器保存消息,接收设备拿到消息,还是用户已经读过?如果界面把这四个状态合并成“成功”,一次断线就会把系统承诺暴露出来。候选即时通信服务把每种确认绑定到具体对象和存储位置。 Facebook Messenger 在这里只表示私聊与群聊题型,不代表其内部实现。范围包括文本消息、离线保存、多设备同步和小群会话,音视频、端到端加密协议以及万人群不在本次实现范围。 候选 SLO 是合法私聊发送从接收到持久化确认在五分钟窗口内 p99 小于 300 ms;设备重新联网且服务端日志仍在保留期内时,99% 的断线补齐在一分钟内完成。群超大扇出和无网络设备不在这些分母中。SQLite 本地脚本只验证重放和去重,不提供真实网络延迟或补齐分位数。 一条消息至少有四个确认点 客户端发送 SEND(conversation_id, client_message_id, payload),服务端身份从认证连接取得,不接受用户自行声明发件人。网关收到消息只表示受理,持久消息库事务提交后才能返回 PERSISTED(message_id, seq)。接收...
系统设计 16:视频服务:转码可以重试,播放清单只发布完整版本
一个视频已经有 720p 的前两个片段,但第三个片段仍在重试。此时发布清单会让播放器拿到一个合法文本,却在播放途中遇到 404。转码成功率、任务去重和播放可用性不是同一个指标;对外确认点应放在必需分段与清单构成完整版本之后。 YouTube、Netflix 在这里表示上传转码与点播分发的题型。候选系统不涉及直播、版权采购、DRM 设计或真实公司的编码参数。实验只验证任务和清单的发布关系,分段是协议测试字节,不能拿它们宣称完成真实视频解码或播放。 候选 SLO 是已发布视频的主清单在五分钟窗口内 p99 小于 200 ms、被引用的必需分段可达率至少 99.9%;新上传视频的编码完成时间需按真实输入与编码器另行定目标。这些是设计指标,不是本地三段标记字节的测试结果;本次 HTTP 检查只覆盖三个固定分段的获取和人为删除后的 404。 上传之后是一张依赖图 POST /videos 创建视频和上传会话,POST /videos/{id}/complete 确认原始对象可用,GET /videos/{id}/status 返回阶段状态,GET ...
系统设计 15:文件同步:断点续传和多端冲突要分别解决
两台电脑都从版本 7 开始编辑同一个文件。A 先上传并提交版本 8,B 随后上传自己的内容。如果服务端只采用最后到达的请求,A 的修改就被静默覆盖;如果只拒绝 B,B 又可能丢掉已经完成的工作。文件同步需要保存字节,也需要保存每次修改相对于哪个版本发生。 Dropbox 在这里表示多端文件同步题型。候选方案支持普通二进制文件、分块上传、离线编辑与冲突副本,不承诺理解任意文档格式并自动合并。正文沿上传恢复和版本提交两条路径展开。 候选 SLO 是全部块已经在服务端校验后的版本提交在五分钟窗口内 p99 小于 500 ms;一旦返回提交成功,新读取要么看到完整新版本,要么在明确隔离的副本延迟窗口中返回旧完整版本,不得看到缺块版本。网络上传、断线补传耗时不计入提交延迟;本地脚本只验证字节校验和条件更新,并未验证该延迟或跨副本行为。 文件身份不等于文件路径 文件拥有稳定 file_id,名称与父目录只是可变元数据。否则重命名会被误识别为删除旧文件再创建新文件,其他设备的未完成上传也会失去归属。基础数据有 files(file_id, parent_id, name, current_v...
系统设计 14:图片社交:上传成功之后还差一次发布提交
客户端收到对象上传成功,并不代表动态列表中已经有一张可展示的图片。缩略图可能未生成,图片可能未通过检查,元数据事务也可能失败。候选图片社交服务把“字节已经保存”和“用户能够看见”拆成两个状态,半成品只能停留在上传会话内。 Instagram 在这里表示上传、处理和展示的题型,不表示公开资料之外的真实产品架构。范围包括原图、固定尺寸缩略图、私密相册和动态展示;图像推荐模型、直播和全功能社交关系留给后续章节。 候选 SLO 是上传已完成且校验通过的原图中 99% 在两分钟内进入 READY 或可解释的终态 REJECTED;动态读取在五分钟窗口内 p99 小于 200 ms。对象云服务、实际解码与异步变体没有进入本次实验,故这些目标尚未被性能验证;半成品不可见才是已测试的不变量。 把发布作为一个明确的接口 POST /uploads 创建会话,返回上传 ID、对象键、允许的大小和类型,以及限时上传凭据。POST /uploads/{id}/complete 提交实际长度和校验信息,服务端读取对象元数据并检查是否符合会话约束。POST /photos/{...
系统设计 13:文本分享:到期拒绝与物理删除是两个时刻
文本分享服务允许用户存一段日志并发给别人。正文放进对象存储之后,数据库删除一行并不代表文本已经消失:缓存、搜索索引、对象版本和备份都可能保留副本。可验证的设计要先给出“何时不再允许读取”,再给出“哪些副本何时清除”,而不是用一个删除按钮替代全部承诺。 场景借用 Pastebin 题型,只讨论纯文本、公开或认证私密分享、有效期与撤销。协同编辑、富文本和全站推荐不在范围内。第 12 篇短链保存的是目标地址,这一篇必须负责正文的存储、交付和生命周期。 候选 SLO 是在线已授权读取在五分钟窗口内 p99 小于 200 ms;撤销事务提交后开始的新读取不得交付正文。物理对象在二十四小时内清理、备份按保留期自然淘汰是待批准的独立生命周期目标,不由这次使用整数时钟的本地实验担保。 不变量沿着访问权限定义 候选接口为 POST /pastes、GET /pastes/{id} 和 DELETE /pastes/{id}。创建时提交 UTF-8 文本、可见性及有效期,服务端校验编码、实际字节长度和最大 1 MiB 限额。返回值包含 ID、到期时间和状态;...














