Feed流使用详解

本文探讨了Feed流的概念,包括其工作原理、分类(按时间与排名)、实现模式(推、拉及推拉结合),以及如何优化千万级Feed流系统,如使用Redis存储、分页器和深度分页策略,以及阿里云的相关实践案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

☆* o(≧▽≦)o *☆嗨~我是小奥🍹
📄📄📄个人博客:小奥的博客
📙📙📙Github:传送门
📅📅📅面经分享(牛客主页):传送门
🍹文章作者技术和水平有限,如果文中出现错误,希望大家多多指正!
📜 如果觉得内容还不错,欢迎点赞收藏关注哟! ❤️

Feed流概念

Feed流是一个目前非常常见的功能,在众多产品中都有展现,比如微博,朋友圈,消息广场,通知,IM等。通过Feed流可以把动态实时的传播给订阅者,是用户获取信息流的一种有效方式。

  • Feed:Feed流中的每一条状态或者消息都是Feed,比如朋友圈中的一个状态就是一个Feed,微博中的一条微博就是一个Feed。
  • Feed流:持续更新并呈现给用户内容的信息流。每个人的朋友圈,微博关注页等等都是一个Feed流。
  • Timeline:Timeline其实是一种Feed流的类型,微博,朋友圈都是Timeline类型的Feed流,但是由于Timeline类型出现最早,使用最广泛,最为人熟知,有时候也用Timeline来表示Feed流。
  • 关注页Timeline:展示其他人Feed消息的页面,比如朋友圈,微博的首页等。
  • 个人页Timeline:展示自己发送过的Feed消息的页面,比如微信中的相册,微博的个人页等。

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

Feed分类

Feed的常见分类有两种:

  • TimeLine:按发布的时间顺序排序,先发布的先看到,后发布的排列在最顶端。
  • Rank:按某个非时间的银子排序,一般是按照用户的喜好度排序等,适用于推荐场景。

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

  • 推模式:当新的 Feed 发布后,将这条内容插入到发布者所有粉丝的 Feed 流中。
  • 拉模式:收到用户拉取Feed流请求后遍历他的关注列表,并拉取关注的人发布的内容实时聚合成 Feed 流。
  • 推拉结合:也叫做读写混合,兼具推和拉两种模式的优点。

两种实现方式各有优缺:

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

Feed流的初始化

Feed流的初始化是指当用户的Feed流还不存在的时候,为该用户创建一个属于自己的Feed流,其实就是遍历一遍关注列表,取出所有的Feed,将FeedId存放到Redis的SortedSet中,score的值如果是TimeLine类型,就取Feed创建的时间戳,如果是rank类型,就把对应权重设置进去。

Feed流的推送

Feed的推送就是更新(这里使用推拉结合模式)。更新分为两类情况:

  • 关注的用户发布、删除新的Feed
  • 用户新增、取消关注

Feed流的存储

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

  • 作者发布的Feed列表:这些数据需要可靠的持久化存储,通常采用MySQL等关系型数据库即可。
  • 用户和作者之间的关注关系:同样需要持久化存储。
  • 用户的Feed流:Feed流可以根据Feed数据库和关注关系构建,因此不需要持久化存储。

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

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

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

持久化存储

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

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

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

Feed流优化

(1) 推拉结合

① 在线推 离线拉

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

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

② 定时推 离线拉

一个拥有 10 万粉丝的大V在发布微博时,以常驻进程的方式定时推送到粉丝的动态列表。

(2) 分页器

由于 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 也不会重复。

(3) 深度分页

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

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

拓展

如何打造千万级Feed流系统-阿里云开发者社区 (aliyun.com)

### 回答1: "fatal: failed to load library 'libcurl-4.dll" 是一个错误信息,通常出现在使用某些软件或应用程序时。这个错误表示系统无法加载 libcurl-4.dll 动态链接库文件。 libcurl-4.dll 是一个用于支持网络通信的动态链接库,它提供了各种网络协议和功能的实现。当软件或应用程序需要使用 libcurl-4.dll 时,操作系统会尝试从指定的路径加载该库文件。然而,如果指定的路径无效或者库文件本身存在问题,就会出现 "fatal: failed to load library 'libcurl-4.dll" 错误。 要解决这个问题,可以尝试以下步骤: 1. 检查 libcurl-4.dll 的路径:确保该文件存在于软件或应用程序所需的路径下。如果文件丢失或被删除,需要重新安装相关软件或应用程序。 2. 检查系统环境变量:有时操作系统无法找到 libcurl-4.dll 是因为环境变量没有正确设置。可以在系统的环境变量中添加正确的路径,并确保路径包含在 PATH 变量中。 3. 更新 libcurl-4.dll:如果库文件本身损坏或过时,可以尝试下载最新的 libcurl-4.dll 版本,并替换当前使用的文件。 4. 检查软件或应用程序的依赖关系:某些软件或应用程序需要其他库文件的支持,如果其中任何一个丢失或损坏,都会导致 "fatal: failed to load library 'libcurl-4.dll" 错误。可以重新安装相关软件或应用程序,或者尝试修复其他缺失的库文件。 如果上述方法仍然无法解决问题,还可以查询相关软件或应用程序的官方支持渠道,寻求更详细的帮助和解决方案。 ### 回答2: 当你在使用或运行某个程序时,如果出现了“fatal: failed to load library 'libcurl-4.dll'”的错误提示,意味着你的计算机缺少了“libcurl-4.dll”这个库文件或者该库文件无法被正确加载。 这个错误通常是由以下几种原因引起的: 1. 缺失库文件:你的计算机上可能没有安装或者该库文件被意外删除了。解决这个问题的方法是下载并安装最新版本的 libcurl-4.dll,或者从可靠的来源获取之前正常工作的文件。 2. 不兼容的库文件版本:你的程序要求的是特定版本的 libcurl-4.dll,但你的计算机上安装了不匹配的版本。在这种情况下,你可以尝试升级你的库文件到与程序要求的版本相匹配,或者尝试与程序兼容的较新版本。 3. 环境变量设置错误:你的计算机可能没有正确设置环境变量,导致操作系统无法找到 libcurl-4.dll 文件的位置。你可以通过检查环境变量设置并添加正确的路径来解决这个问题。 4. 程序文件损坏:有时,libcurl-4.dll 文件本身可能被损坏。你可以尝试重新下载并替换该文件,确保你使用的是完整且未损坏的文件。 总之,解决这个错误的关键在于确保计算机上正确安装了所需的库文件,并且文件能够被正确加载。如果以上方法无效,你可以尝试重新安装或者更新相关的程序,或者咨询专业人士以获得更详细的帮助。 ### 回答3: 这个错误表示在运行某个程序时,系统无法加载'libcurl-4.dll'库文件。这个库文件是用于支持网络通信功能的,通常与网络连接、数据传输等操作相关。这个错误可能有以下几种原因和解决方法: 1. 缺少库文件:最常见的情况是缺少'libcurl-4.dll'文件。解决方法是重新安装或更新相关程序或软件。可以尝试下载并安装最新版本的 libcurl 库,并确保它位于正确的目录下。 2. 版本不匹配:可能库文件的版本与程序或软件的要求不匹配。可以尝试使用与程序或软件兼容的特定版本的'libcurl-4.dll'库文件。 3. 文件损坏:如果库文件损坏或被破坏,就会导致加载失败。可以尝试重新下载库文件,或者从可信的来源获得原始文件并替换。 4. 环境变量设置错误:在某些情况下,系统无法正确查找到库文件的路径。可以通过设置正确的环境变量来解决这个问题。确保将库文件所在的目录添加到系统的PATH环境变量中。 5. 冲突或错误的系统配置:某些软件或驱动程序可能会导致冲突或干扰,从而无法加载库文件。可以尝试重新安装相关程序,或者更新操作系统和驱动程序来解决冲突问题。 总之,'fatal: failed to load library 'libcurl-4.dll'的错误通常可以通过重新安装或更新相关程序、替换库文件、设置正确的环境变量或解决系统冲突来解决。如果问题仍然存在,可以考虑咨询技术支持或论坛等资源以获取更多帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值