背景
Feed 流在 游戏内 UGC 内容社区(朋友圈,关卡)中有着广泛应用,比如首页推荐、关注页、话题页等。本文结合我们在 UGC 系统中的实践,说明不同架构模式与实现要点。

Feed 是指状态或消息,Feed 流是一个持续更新、并按照特定排序策略向用户展示的个性化内容序列。
- 基于时间:全局时间线与关注创作者时间线。
- 基于热度/权重:按互动数据(点赞、评论、转发等)计算热度。
- 基于兴趣:基于用户历史行为的召回与重排。
本文聚焦“基于关注的单向关系(关注创作者)”的时间线实现。
功能范围:
- 发布作品:创作者发布图文/视频内容。
- 获取 Feed 流:关注页与个人主页时间线。
- 关注关系:关注/取关创作者。
对应的数据与系统关注点:
- 存储:保存创作者发布的数据。
- 同步:保存用户可读取的数据(收件箱/发件箱视图)。
- 元数据:关注关系与用户信息。
核心架构模式:推与拉的博弈
模式一:拉模式 (Fan-out-on-Load / Pull)
* **工作原理**:
* 写扩散低:发布仅写入自己的发件箱。
* 读聚合:读取时查询所有关注者发件箱,聚合、排序后返回。
* **流程**:用户请求 → 查询关注列表 → 并行查询发件箱 → 聚合排序 → 返回 Feed
```mermaid
sequenceDiagram
participant U as 用户
participant C as 客户端
participant API as API 网关
participant R as 关系服务
participant O as 发件箱存储
participant F as Feed 服务
U->>C: 打开关注页
C->>API: GET /feed?cursor=...
API->>R: 查询关注创作者列表
API->>O: 并行拉取各发件箱最新内容
O-->>API: 返回候选内容集合
API->>F: 聚合/去重/排序
F-->>C: 返回分页结果
```
* **优点**:
* 写轻量,发布快。
* 无冗余,存储小。
* 适合关注关系稀疏的场景。
* **缺点**:
* 读昂贵,延迟高。
* 容易形成数据库瓶颈。
* **注意点**
* 深翻页陷阱:避免 `LIMIT offset, count`。
* 建议游标分页:`WHERE id < last_id ORDER BY id DESC LIMIT 20`。
* Redis ZSET 可用 `ZREVRANGEBYSCORE`。 ### 模式二:推模式 (Fan-out-on-Write / Push)
* **工作原理**:
* 写扩散:发布时查询粉丝,将内容写入每个粉丝收件箱。
* 读直接拉取:用户读取时按页直接从自身收件箱获取。
* **流程**:发布 → 查询粉丝 → 并行写收件箱 → 读取 → 直接查收件箱
```mermaid
sequenceDiagram
participant U as 创作者
participant C as 客户端
participant API as API 网关
participant UGC as UGC 服务
participant MQ as 消息队列
participant F as Fan-out 消费者
participant R as 关系服务
participant I as 收件箱(Redis)
U->>C: 发布作品
C->>API: POST /ugc
API->>UGC: 校验并保存作品
UGC-->>MQ: 发送"内容发布"事件
F->>R: 拉取粉丝列表
F->>I: 批量写入粉丝收件箱
Note right of I: 读路径直接分页拉取
```
* **优点**:
* 读极快,体验好。
* 适合高并发读(头部创作者)。
* **缺点**:
* 写重,发布延迟高。
* 存储冗余大。
* 关系变更处理复杂。 ### 混合模式:现实世界的选择
* **场景分析**:多数系统并非纯推或纯拉。
* **典型方案**:
* 普通用户用推:保障大多数用户读取速度。
* 大 V 用拉:超过阈值时仅推活跃粉,其余读时拉取并混排。
* **优点**:读写性能与成本平衡。
* **缺点**:
* 系统更复杂,容灾与回退更难。
* 阈值/策略调优复杂,边界抖动。
* 幂等合并更难,需避免重复与错序。
* 一致性成本高,取关清理与补偿任务增加。
* 峰值难预测,需双侧容量预留。
* 监控排障更难,跨多环节定位。
* 降级策略复杂,需无感退化。
团队现状与演进方案
现状
以拉为主(Fan-out-on-Load),各项目单独实现。
考虑因素
- 规模与关系图:粉丝中位数低、关注关系稀疏,读 QPS 可控。
- 研发效率:读侧统一去重/聚合/排序,上线快、维护低。
- 成本与风险:无冗余写、存储小,避免写扩散热点与雪崩。
问题
- 活跃用户与头部创作者增加后,读侧聚合放大、深翻页增多。
实践:L22 UGC 发布提醒的推-拉结合
背景
订阅作者发布新作品提醒为高 QPS 红点服务,直接拉取关注列表并查 Feed 表会带来较大 DB 压力。
方案概述
- Push:作品发布/生效时刷新作者最新作品视图,确保读路径低延迟。
- Pull:客户端轮询获取是否有新订阅作品,读取后回写已读/短期忽略。
接口
- GET
/notification/subscription/status→ 读取是否有新订阅作品,返回最新作品摘要。 - POST
/notification/subscription/read→ 标记已读与“近期不再提醒”窗口。
缓存与缓存内容
- InformProfileCache (
inform_profile_s9:<roleId>,30m):用户提醒偏好。 - FollowedRoleIdsCache (
FollowedRoleIds:<roleId>,20m):用户关注的作者 ID 列表。 - CreatorLastestValidWorkCache (
CreatorLastestValidWork:<creatorRoleId>,24h):作者最新有效作品快照(WorkId、WorkCtime)。 - NotificationSubscriptionStatusCache (
RoleSubscriptionStatus:<roleId>,30m):订阅提醒状态(LastReadTime、IgnoreUntilTime)。
整体流程
sequenceDiagram
participant U as 作者端/管理端
participant C as Client
participant A as API
participant S as NotificationService
participant R as Redis Caches
participant D as DB
rect rgba(200,255,200,0.3)
note right of U: Push: 作品发布/生效
U->>D: 持久化作品(含 Ctime)
U->>R: 刷新 CreatorLastestValidWorkCache(creatorRoleId)
end
rect rgba(200,200,255,0.3)
note over C,A,S: Pull: 客户端轮询读取
C->>A: GET /notification/subscription/status
A->>S: NotificationSubscriptionStatus(req)
S->>R: Get InformProfileCache(roleId)
S->>R: Get NotificationSubscriptionStatusCache(roleId)
S->>R: Get FollowedRoleIdsCache(roleId)
S->>R: Gets CreatorLastestValidWorkCache(followedRoleIds)
S->>D: Fetch Work detail(必要时)
S-->>C: HasNewSubscription? + Work(可选)
end
rect rgba(255,230,200,0.3)
note over C,A,S: Pull: 回写已读/忽略
C->>A: POST /notification/subscription/read
A->>S: NotificationSubscriptionRead(req)
S->>D: Save LastReadTime/IgnoreUntilTime
S->>R: Set NotificationSubscriptionStatusCache(roleId)
S-->>C: OK
end
最终目标
参考
- 标准参考:ActivityStreams RFC
- 开源参考:Stream-Framework
OKR(2025 Q4 — 2026 Q1)
- O1 统一 Feed 基础设施落地
- KR1 发布内部规范与 SDK v1,覆盖收/发件箱、游标分页、幂等去重
- KR2 完成 2 个存量项目 + 1 个新项目接入,零 P0 事故
- KR3 关注页读取 P95 < 120ms、P99 < 300ms;错误率 < 0.1%
- KR4 峰值读侧 DB QPS 较现状下降 ≥ 40%,缓存命中率 ≥ 90%
- O2 推-拉混合能力最小可用闭环
- KR1 支持按粉丝量/活跃度阈值自动切换;策略灰度与回退可用
- KR2 取关清理与补偿任务上线;重复/错序率 < 0.05%
- KR3 提供读写降级与熔断开关,30 分钟内完成回退
- O3 可观测性与工程化完善
- KR1 完成端到端看板与告警,覆盖 99% 关键链路
- KR2 建立压测基线与容量模型,通过 10x 峰值演练
- KR3 完成文档与 Playbook,举办 2 场培训,满意度 ≥ 4.5/5
结合我们的业务场景与团队架构,产出一套内部规范与 SDK,提升复用、降低成本、增加稳定性。