设计 Instagram Stories:从上传到过期
发布: (2026年1月31日 GMT+8 02:08)
5 min read
原文: Dev.to
Source: Dev.to
核心需求
功能需求
- 用户可以发布照片或视频故事
- 故事在 24 小时后自动过期
- 可见性受限(粉丝、亲密好友、联系人)
- 观看者可以查看并对故事作出反应
非功能需求
- 低延迟的动态加载
- 高可用性
- 横向可扩展性
- 最终一致性是可以接受的
高层架构(HLD)
在高层次上,系统被划分为独立的服务,每个服务负责单一职责:
- API Gateway – 身份验证、授权、路由、限流
- Story Service – 故事创建与生命周期管理
- Content Service – 媒体、文本和链接处理
- Feed Service – 故事动态生成
- Visibility Service – 隐私和受众强制执行
- Expiration Service – 24 小时 TTL 处理
- Kafka & Background Workers – 异步处理
- Analytics & Notification Services – 参与度洞察和通知
故事创建流程(写路径)
用户发布故事时:
- 客户端通过 API Gateway 发送请求。
- Content Service 返回预签名的上传 URL。
- 客户端直接将媒体上传到对象存储(如 S3)。
- Story Service 保存带有 24 小时过期时间戳的元数据。
关键设计决策: 将媒体上传与元数据存储分离,使写路径保持快速且可扩展。
故事消费流程(读路径)
用户打开故事托盘时:
- Feed Service 从关注的用户中获取活跃的故事。
- Visibility Service 根据隐私规则过滤故事。
- 已过期的故事被忽略。
- 将媒体 URL 返回给客户端。
- 客户端直接从 CDN 流式传输媒体。
该设计针对以读取为主的流量进行了优化,因为读取流量在故事使用中占主导。
可见性和隐私规则
故事支持多种可见性模式:
- 仅限粉丝
- 亲密好友
- 基于联系人的可见性(WhatsApp 状态)
- 被屏蔽的用户
专门的 Visibility Service 使用以下方式强制执行这些规则:
- 粉丝/联系人图谱
- 用于快速权限检查的 Redis 缓存
将可见性逻辑隔离可确保隐私执行的一致性,并便于后续演进。
过期与生命周期管理
短暂内容被视为第一类关注点:
- 每条故事都有严格的 24 小时 TTL。
- Expiration Service 监控故事时间戳。
- 过期的故事触发生命周期事件。
- 过期内容不再提供服务。
即使在高流量情况下也能保证正确性。
使用 Kafka 的事件驱动清理
Kafka 将生命周期事件与清理逻辑解耦。典型事件包括:
story_createdstory_expiredstory_viewedstory_reacted
Media Cleanup Worker 订阅过期事件并执行:
- 从对象存储中删除媒体。
- 移除 CDN 引用。
清理工作异步进行,保持面向用户的 API 快速响应。
参与度追踪(观看与反应)
用户参与度由独立的服务处理:
- View Tracking Service – 追踪故事观看次数。
- Reaction Service – 点赞、表情符号和回复。
这些服务:
- 处理极高的写入吞吐量。
- 采用最终一致性。
- 不影响动态读取性能。
参与度数据随后会被聚合用于分析。
最后思考
故事系统看似简单,实则复杂。通过专门为过期、可见性和规模设计,我们能够构建出弹性好、效率高且易于演进的系统。该设计与 Instagram、WhatsApp 等平台在大规模处理短暂内容的方式高度相似。欢迎提供反馈和替代方案。