系统设计:Feed 流系统
Feed 流(信息流)是社交应用的核心功能,包括微信朋友圈、微博、抖音推荐流等。核心挑战是如何在亿级用户下高效分发内容。
1. 需求分析
场景对比
| 产品 | 关系 | 内容类型 | 分发策略 |
|---|---|---|---|
| 微信朋友圈 | 双向关注 | UGC | 推模式(写扩散) |
| 微博 | 单向关注 | UGC/PGC | 推拉结合 |
| 抖音 | 单向关注 | 短视频 | 推荐引擎 |
| 单向关注 | 短文本 | 推模式为主 |
核心指标
- 发布延迟:< 1 秒
- 刷新延迟:< 200ms
- 一致性:最终一致
2. 推模式 vs 拉模式
推模式(Write Fan-out)
用户A发布内容时,推送到所有粉丝的收件箱。
发布者 → 写入自己发件箱 + 推送到所有粉丝收件箱
↓
N 个粉丝收件箱
优点:读取快,直接读收件箱
缺点:大V发布时写入量巨大(1000 万粉丝 = 1000 万次写入)
拉模式(Read Fan-out)
用户刷新时,拉取所有关注者的最新内容,合并排序。
用户请求 → 获取关注列表
↓
读取每个关注者的发件箱
↓
合并排序返回
优点:发布零成本
缺点:读取慢,关注人数多时延迟高
混合模式
| 用户类型 | 策略 |
|---|---|
| 普通用户(粉丝 < 1 万) | 推模式 |
| 大V(粉丝 ≥ 1 万) | 拉模式,或只推在线用户 |
3. 系统架构
发布内容 → 内容服务 → 存储系统
↓
消息队列(Kafka)
↓
┌─────────┴─────────┐
↓ ↓
粉丝 < 1万 粉丝 ≥ 1万
↓ ↓
推送到收件箱 标记为拉取
(Redis List)
4. 核心设计
4.1 收件箱存储
Redis 有序集合(Sorted Set),按时间戳排序:
ZADD inbox:user_100 1695680000 "tweet:12345"
ZADD inbox:user_100 1695680100 "tweet:12346"
ZRANGE inbox:user_100 0 20 WITHSCORES # 取最新 20 条
4.2 冷数据归档
- 收件箱只保留最近 N 天(如 7 天)
- 冷数据归档到 HBase / S3
- 用户浏览历史数据时,异步加载
4.3 Timeline 排序
时间序:纯按发布时间排序(微信朋友圈)
智能排序(Edge Rank):
Score = 亲密度 × 内容质量 × 时间衰减
亲密度:互动频率
内容质量:点赞/评论/转发率
时间衰减:越新分数越高
4.4 社交图存储
关注关系用图数据库或分布式存储:
用户A 关注 [用户B, 用户C, ...]
用户B 粉丝 [用户A, 用户D, ...]
分片策略:按粉丝 ID 范围分片,或按关注者 ID 哈希分片。
5. 性能优化
预加载
用户刷新前,预加载下一页内容到缓存。
本地缓存
移动端缓存最近 N 条,减少请求。
CDN
媒体资源(图片、视频)走 CDN 加速。
6. 面试常见问题
Q: 为什么 Twitter 早期用拉模式后来改推模式?
拉模式在关注人数少时简单,但用户关注数百人后读取延迟太高。推模式用空间换时间,适合读多写少的场景。
Q: 大V的「拉模式」怎么实现高效读取?
- 限制拉取数量(如最近 1000 条)
- 为大V单独建缓存发件箱
- 异步预计算大V的内容索引
Q: 如何处理删除内容?
- 软删除(标记删除,延迟清理)
- 发布删除指令到消息队列,异步清理各粉丝收件箱
相关文章:
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。