新闻订阅系统的设计和实现
- Web 服务器:Web 服务器将流量重定向到不同的内部服务。
- Post 服务:在数据库和缓存中持久化帖子。
- Fanout 服务:将新内容推送到朋友的新闻订阅中。新闻订阅数据存储在缓存中以便快速检索。
- 通知服务:通知朋友新内容可用,并发送推送通知。
Web 服务器
除了与客户端进行通信,Web 服务器还执行身份验证和速率限制。只有使用有效的 auth_token 登录的用户才能发布帖子。系统限制用户在一定时间内可以发布的帖子数量,这对于防止垃圾邮件和恶意内容至关重要。
扩散服务
扩散是将帖子传递给所有朋友的过程。有两种类型的扩散模型:写时扩散(也称为推送模型)和读时扩散(也称为拉取模型)。
- 从图数据库获取朋友ID。图数据库适合管理朋友关系和朋友推荐。有兴趣了解更多关于这个概念的读者,可以参考参考资料[2]。
- 从用户缓存获取朋友信息。然后系统根据用户设置过滤朋友。例如,如果你屏蔽了某人,即使你们仍然是朋友,她的帖子也不会出现在你的新闻订阅中。帖子可能不显示的另一个原因是,用户可能选择性地与特定朋友分享信息,或者从其他人那里隐藏信息。
- 将朋友列表和新帖子ID发送到消息队列。
- 扩散工作器从消息队列获取数据,并将新闻订阅数据存储在新闻订阅缓存中。你可以将新闻订阅缓存看作是一个 映射表。每当发布一个新帖子,它都会被添加到图 11-6 中显示的新闻订阅表中。如果我们在缓存中存储整个用户和帖子对象,内存消耗可能会变得非常大。因此,只存储ID。为了保持内存大小小,我们设置了一个可配置的限制。用户在新闻订阅中浏览成千上万的帖子的机会很小。大多数用户只对最新的内容感兴趣,所以缓存未命中率很低。
- 在新闻订阅缓存中存储 。图 11-6 显示了缓存中的新闻订阅的样子。
写时扩散:在这种方法中,新闻订阅在写入时预先计算。新帖子发布后立即发送到朋友的缓存。
## 优点:
- 新闻订阅是实时生成的,可以立即推送给朋友。
- 因为新闻订阅在写入时就预先计算,所以获取新闻订阅非常快。
## 缺点:
- 对于明星用户来说,获取朋友列表并为他们所有人生成新闻订阅是缓慢且耗时的。这就是所谓的热键问题。
- 对于不活跃的用户或者很少登录的用户,预先计算新闻订阅会浪费计算资源。
读时扩散: 在读取时生成新闻订阅,这是一个按需模型。用户加载主页时,会拉取最近的帖子。
## 优点:
- 对于不活跃的用户或者很少登录的用户,读时扩散效果更好,因为它不会在他们身上浪费计算资源。
- 数据不会推送给朋友,所以没有热键问题。
## 缺点:
- 获取新闻订阅速度慢,因为新闻订阅没有预先计算。
**混合扩散:**由于快速获取新闻订阅很关键,所以我们对大部分用户使用推送模型。对于那些有许多朋友/粉丝的名人或用户,我们让粉丝按需拉取新闻内容,以避免系统过载。
新闻获取服务
- 网络服务器调用新闻订阅服务获取新闻订阅。
- 新闻订阅服务从新闻订阅缓存获取帖子 ID 列表。
- 新闻订阅服务从缓存(用户缓存和帖子缓存)中获取完整的用户和帖子对象,以构建完全填充的新闻订阅。
- 完全填充的新闻订阅以 JSON 格式返回给客户端进行渲染。
新闻缓存结构设计
- 新闻订阅:存储新闻订阅的 ID。
- 内容:存储每个帖子的数据。热门内容存储在热缓存中。
- 社交图:存储用户关系数据。
- 行动:存储用户是否喜欢一篇帖子,回复一篇帖子,或对一篇帖子进行其他操作的信息。
- 计数器:存储点赞、回复、关注者、正在关注等的计数器。