这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天。
前言
本次青训营的大项目需要我们实现一个极简化的抖音后端。 而类抖音平台的一个极重要的组成部分便是它们的 feed 流分发部分。 本文总结了以下的一些文章,提取出了一些可能的设计思路。
参考文章
概念:Feed 流
Data feed is a mechanism for users to receive updated data from data sources.
Feed 这一概念主要指的是把信息从数据源发送给用户的机制。 只要产品里涉及到信息的发布者和接受者,那么架构中就一定会涉及到 feed。 Feed 实现可以偏向简单也可以非常复杂,例如:
- 最简单的 RSS 中,数据源提供一个信息列表,用户需要自己进行轮询。
- 最简单的邮件列表系统中,数据源负责将邮件一封一封分别发送到每一位订阅者的邮箱。
- 微博里用户不应收到其拉黑的用户的信息。
- 微博里,时间线可以分为两种类型:
- 按时间排序;
- 综合各种条件产生的乱序时间线。
总之,根据平台性质、流量、需求的不同,其架构设计可能也会有不同。 一般来说,feed 流可以分为推模式和拉模式。
拉模式
用一条(未经优化的)SQL 语句也许更言简意赅:
SELECT * FROM video JOIN follow
ON video.author = follow.following
WHERE follow.follower = 'my_user_id'
ORDER BY video.updated DESC
LIMIT 30 OFFSET 0;
用户每请求一次 feed 流,我们都需要进行至少一次复杂的 SQL 请求:
- 将用户所关注的所有信息发布者所发布的信息汇总起来;
- 按某种逻辑将这些信息排序(上面的 SQL 简单地按时间排序了);
- 进行分页。
因为这种机制是在用户请求的时候再从源头拉取信息来组织时间线,这种模式被称为“拉模式”。 上面提到的 RSS 就是一个拉模式的典型例子。
推模式
一些开源项目使用邮件列表来进行交流(如 mail.openjdk.org)。 邮件列表系统是推模式的一个典型例子:
- 每个人都有一个邮箱;
- 当某个人将邮件发到邮件列表时,系统会将这封邮件转发到所有订阅了的人手上;
- 订阅者的邮箱就是自己的 feed。
推/拉模式比较
推模式 | 拉模式 | |
---|---|---|
发布耗时 | 正比于粉丝数 | 小 |
请求耗时 | 小 | 正比于发布者数及其历史发文数 |
分页 | 建索引即可 | 必须实时计算 |
储存空间 | 正比于粉丝数、发文数 | 小 |
拉模式有自己的优势。 但是大多数的平台中,读者请求数都是大大多于作者发布数的, 因而请求时间小的推模式具有极大的优势。 另外,推模式也适于加入个性化内容和选择性推送功能。 而现有的大多数平台架构也都基于推模式。
架构
推模式的架构在数据人看Feed流-架构实践一文已有详细论述。 限于个人水平,这里就不再妄加评论了。
推模式:储存
推模式:实际考量
当然,在实际进行代码编写的时候我们还要考虑一些问题:
- 当用户 A 关注用户 B 的时候,我们需不需要更新用户 A 的 feed 以加入 B 的内容?
- 当用户 A 取关用户 B 的时候,我们需不需要更新用户 A 的 feed以删去内容?
- 如果上面两个问题的答案为“是”,那么有没有可能出现下面的情况?
- 用户 A 关注 B 时,B 恰好发布了一篇文章,这篇文章有可能永远不会出现在 A 的 feed 里。
- 用户 A 取关 B 时,B 恰好发布了一篇文章,这篇文章有可能并不会被从 A 的 feed 里删去。
上面的两种情况甚至用户可能也不会太在意,但却是的的确确的逻辑漏洞。 其触发的并发执行情况如下:
A 取关过程 | B 分发过程 |
---|---|
获取 B 的粉丝列表(包含 A) | |
将 A 从 B 的粉丝列表删去 | |
将 B 的内容从 A 的 feed 删去 | |
将 B 的新内容放入粉丝的 feed 中 | |
现在 A 不是 B 的粉丝了 | 但是 A 的 feed 里仍然有 B 的内容 |
这种情况在 B 的粉丝数量极大时可能会经常出现,因为此时 B 的新内容的分发可能会需要较多时间, 在这段时间里发生的关注或取关操作便很可能会触发这种漏洞。
同时,因为 B 的分发过程耗时长,所有基于锁的解决方案都可能会有性能问题。 个人的想法是暂存一下发生变化的用户关系并在必要时进行检查。 当然,我们也可以就这么希望着用户永远不会留意到这种情况。
总结
推模式是主流的选择。但推/拉模式的选择只是 feed 流架构设计的开始,考虑了储存、负载均衡、缓存等各种优化手段后的实际架构比“推”“拉”二字会复杂得多。 数据人看Feed流-架构实践一文中推荐了初创公司的一种迭代路径,其架构设计值得参考。