Feed 流系统杂谈

标签: feed 系统 | 发表时间:2022-05-27 10:24 | 作者:Finley
出处:https://juejin.cn/tag/%E6%9E%B6%E6%9E%84

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天, 点击查看活动详情

什么是 Feed 流

Feed 流是社交和资讯类应用中常见的一种形态, 比如微博知乎的关注页、微信的订阅号和朋友圈等。Feed 流源于 RSS 订阅, 用户将自己感兴趣的网站的 RSS 地址登记到 RSS 阅读器中, 在阅读器里聚合成的列表就是 Feed 流。

Feed 流的本质是 M 个用户订阅了 N 个信息源形成的多对多关系,Feed 流系统需要聚合用户订阅的 N 个信息源产生的信息单元(Feed),并按照一定顺序排列后推送给用户。

接下来我们以关注页场景为例来介绍 Feed 流的实现。

Feed 流有两种基本实现模式:

  • 推模式:当新的 Feed 发布后,将这条内容插入到发布者所有粉丝的 Feed 流中。
  • 拉模式:收到用户拉取Feed流请求后遍历他的关注关系,并拉取关注的人发布的内容实时聚合成 Feed 流。

两种实现方式各有优缺:

  • 推模式的优点在于可以迅速响应用户拉取 Feed 流的请求。但是在粉丝数较多的大V发布内容时需要在他每个粉丝的Feed流中一一进行插入,会产生较大的峰值负载。由于 Feed 发布后的插入操作较多, 通常需要使用 MQ 来异步地进行。
  • 拉模式的优点在于大V发布内容时不会产生峰值负载,但是实时构建 Feed 流操作需要用户等待较多时间。

在实际应用中我们通常采取推拉结合的实现方式。在具体介绍推拉结合之前,我们先来讨论一下 Feed 流系统的存储。

Feed 流的存储

Feed 流系统中需要存储的数据有 3 部分:

  1. 作者发布的 Feed 列表:这些数据需要可靠的持久化存储,通常采用 MySQL 等关系型数据库即可。因为很可能需要按照发布时间排序, 若要使用 NoSQL 最好使用支持有序存储的数据库。
  2. 用户和作者之间的关注关系:同样需要可靠的持久化存储,采用 MySQL 等关系型数据库或者 KV 结构的 NoSQL 数据库均可。
  3. 用户的 Feed 流:Feed 流可以根据 Feed 数据库和关注关系构建,因此可以不做持久化存储。

最轻量的解决方案是使用 Redis 存储 Feed 流。在数据量较大 Redis 内存不够用时,也可以采用一些持久化的存储方案。

Redis 的 SortedSet 是非常适合存储 Feed 流的数据结构。一般以 Feed 的 ID 作为 SortedSet 的 member,时间戳或者热度值、推荐值作为 score 进行排序。SortedSet 保证了 Feed 不会重复,且插入过程线程安全,无论是推拉模式实现起来都非常方便。

为了避免 Redis 中缓存的 Feed 流占用过多内存,通常需要给 Feed 流设置 TTL.

Feed 的具体内容存储可以在 MySQL 中,同时在 Redis 中做一层缓存。关注关系可以存储在 MySQL 中,因为有些大V的粉丝数较多所以不推荐用 Redis 缓存。

持久化存储

一个用户的 Feed 流大小是他所有关注者发布的 Feed 数总和。在用户量较大的系统中 Feed 流数据量巨大且增长迅速,将所有 Feed 流存储在 Redis 中需要消耗巨量的内存。

在必要的时候可以利用持久化存储作多级缓存,比如:将当日活跃用户的 Feed 流数据存储在 Redis 中, 当月活跃用户的 Feed 流持久化到数据库中,长期未活跃的用户则在他重新登录后使用 MySQL 中存储的关注关系重新构建 Feed 流。

因为持久化存储 Feed 流的数据库需要有较大的数据容量、较高吞吐量并且需要支持排序,所以不建议使用数据容量较小的 MySQL 或者不支持排序的 KV 数据库来存储 Feed 流数据。

作者推荐使用 Cassandra 来持久化存储 Feed 流:使用用户的 UID 作为 Partition Key, Feed 时间戳在前 Feed ID 在后, 共同作为 Clustering Key 用于排序和去重。Cassandra 支持 TTL 可以用来自动清除冷数据。

另外,由于Feed 流数据属于只追加不修改与 Cassandra 使用的 LSM 结构非常契合,可以有效减少 Cassandra 进行 Compaction 的负担。

Feed 流系统优化

在线推 离线拉

一个拥有 10 万粉丝的大V在发布微博时,他的粉丝中可能只有 1 千人在线。因此我们常用的优化策略是:对于在线的粉丝采用推模式,将新的 Feed 直接插入到粉丝的信息流中;对于离线的粉丝采用拉模式,在粉丝登录时遍历他的关注关系重新构建 Feed 流。

在线推的部分需要计算粉丝和在线用户的交集,然后进行插入操作。因为在线用户数和粉丝数都比较大,所以计算交集的过程需要分批进行。比如说每次查询 100 个粉丝,然后去查询这 100 个用户中有多少在线(取交集),直到遍历完粉丝列表。这个过程类似于将两个表做 join, 同样适用 小表驱动大表的原则以减少取交集操作的次数, 大多数情况下使用数量较少的粉丝表作为驱动表。(不要问我什么情况下用在线用户表做驱动表)

分页器

由于 Feed 流通常比较大,不可能一次性将所有内容拉取到本地,所以一般需要支持分页查询。

若在用户浏览过程中他关注的人发布了新的内容,导致原来在第 1 页最后一位的 Feed A 被挤到了第 2 页首位。在使用 Limit + Offset 分页器拉取第 2 页时就会再次拉到 Feed A。于是客户端上显示了两条相同的内容,这个问题非常影响用户体验。

解决重复问题最简单的方法是使用 LastId + Limit 式的分页器。客户端加载下一页时使用本地最后一个 Feed 的 ID 作为游标,服务端使用 ZRangeByScore 命令获得发布时间比它更早的 Feed 作为下一页。无论浏览过程中 Feed 流内被插入了多少新内容,只要 Feed 的时间戳唯一就不会下发重复的 Feed.

一个简单实用的避免时间戳重复的方法是:以发布时间作为 score 的整数部分,Feed ID 作为小数部分。这样 Feed ID 不会干扰排序,此外 Feed ID 不会重复所以 score 也不会重复。

深度分页

由于 Feed 流比较大而用户大多数时候只浏览最新的内容,所以通常不需要缓存全部 Feed 流只需要缓存最新的部分即可。但是我们无法阻止用户继续向下浏览未缓存的内容,所以还是得想办法支持深度分页。

我们在实践中采用的解决方案是: 默认缓存最近一个月的数据,当用户快浏览完缓存内容时则异步地采用拉模式构建最近一年的 Feed 流缓存起来。当用户快读完最近一年的内容时继续缓存更旧的 Feed 流,直至缓存了完整 Feed 流。在追加 Feed 流缓存的同时减少它的 TTL, 以避免过大的 Feed 流长期占据内存。

相关 [feed 系统] 推荐:

Feed 流系统杂谈

- - 掘金 架构
这是我参与「掘金日新计划 · 6 月更文挑战」的第2天, 点击查看活动详情. Feed 流是社交和资讯类应用中常见的一种形态, 比如微博知乎的关注页、微信的订阅号和朋友圈等. Feed 流源于 RSS 订阅, 用户将自己感兴趣的网站的 RSS 地址登记到 RSS 阅读器中, 在阅读器里聚合成的列表就是 Feed 流.

Feed 流系统设计总纲

- - 行业应用 - ITeye博客
差不多十年前,随着功能机的淘汰和智能机的普及,互联网开始进入移动互联网时代,最具代表性的产品就是微博、微信,以及后来的今日头条、快手等. 这些移动化联网时代的新产品在过去几年间借着智能手机的风高速成长. 这些产品都是 Feed 流类型产品,由于 Feed 流一般是按照时间“从上往下流动”,非常适合在移动设备端浏览,最终这一类应用就脱颖而出,迅速抢占了上一代产品的市场空间.

微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨

- 荷泽 - 博客园-草屋主人的blog
微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨.      [文章作者:孙立 链接:http://www.cnblogs.com/sunli/ 更新时间:2010-08-24].      sns系统,微博系统都应用到了feed(每条微博或者sns里的新鲜事等我们称作feed)系统,不管是twitter.com或者国内的新浪微博,人人网等,在各种技术社区,技术大会上都在分享自己的feed架构,也就是推拉模式(timyang上次也分享了新浪微薄的模式).

常用社交网络(SNS、人人网、新浪微博)动态新闻(feed、新鲜事、好友动态)系统浅析

- - 互联网 - ITeye博客
原文地址:http://blog.csdn.net/sunmenggmail/article/details/8472546. 最近见几个朋友都在说人人网新鲜事排序的问题,恰巧对这方面也较感兴趣,于是打算顺便把手头收集到的资料梳理学习一下. 由于本人也只是新手,很多内容仅仅是参阅资料后的个人猜测与纸上谈兵故难免存有错误与纰漏,感谢大家指正.

Feed消息队列架构分析

- - Tim[后端技术]
最近一两年,大部分系统的数据流由基于日志的离线处理方式转变成实时的流式处理方式,并逐渐形成几种通用的使用方式,以下介绍微博的消息队列体系. 当前的主要消息队列分成如图3部分. 1、feed信息流主流程处理,图中中间的流程,通过相关MQ worker将数据写入cache、Redis及MySQL,以便用户浏览信息流.

Feed架构-我们做错了什么

- - Tim[后端技术]
在过去几年,所在的微博技术团队在一定程度成功解决了feed架构的扩展性与性能的问题,大部分精力已经从应对峰值性能或者数据扩展中解放出来. 几天前,拿着上面这张架构图问内部一些架构师,目前完成的工作及存在的主要问题是什么. 完成的工作不出意料,大家的观点比较类似,主要在架构的工程成熟度方面. 解决了数据规模大且长尾访问的问题,通过按时间线的冷热分区设计,在MySQL等数据库上成功实现了低成本的长尾分区实现.

Pinterest的Feed架构与算法

- - 后端技术 by Tim Yang
Pinterest首页的Feed消息流,最早是按照用户的关注对象的Pin(类似微博)聚合后按时间进行排序(自然序,类似朋友圈),后来版本的feed系统放弃了自然序,而是根据一定规则及算法来设计,内部称之为Smart feed,其算法及架构根据其公开资料整理如下,值得业界做信息流产品的技术架构师参考.

RSS Feed Search Engine -RSS 專用搜尋引擎

- votis - 免費資源網路社群
RSS Search Engine 是由知名部落格 Digital Inspiration 所建置的服務,主要功能是用來協助使用者發掘網路上的熱門 RSS Feeds,如同搜尋引擎,可以填入自己有興趣的主題,它就會找出相關熱門網站,比較不同的是會一併顯示 RSS 資訊,能更方便訂閱網站. 網站名稱:RSS Search Engine.

NLP 技术在微博 feed 流中的应用

- - IT瘾-tuicool
分享嘉宾:董兴华 新浪微博. 内容来源:DataFunTalk. 导读:新浪微博截止2019.9统计的数据,月活跃用户数为4.97亿,日活跃用户数为2.16亿,其中约94%为移动端用户,今天会和大家分享新浪微博在 feed 流中遇到的 NLP 问题和解决思路. ——难点与现存问题——. ❶  博文内容大多比较短.

提供社群網站 RSS feed 的服務

- - Gea-Suan Lin's BLOG
在 Hacker News Daily 上看到的服務:「 RSS Box」,主要是有 open source,所以可以自己架起來跑 (只是得自己生 API key):「 RSS Box」. 測了一下目前的站台, Twitter 與 Instagram 的部份都已經撞到 rate limit,而 YouTube 的部份正常.