方案扩展

本文介绍Feed流系统的两种扩展模型:推拉结合方案和加入排序后的Rank流方案。

推拉结合方案

虽然使用推模式可以满足Feed流系统需求,但随着用户数量增长,数据量也急剧增长。在推模式的工作下,数据量会膨胀得更多。针对这个缺点,可以考虑采用推拉结合的推动方案。

image.png

推拉结合是指对大V采用拉模式,而普通用户使用推模式。此时发布Feed和获取Feed流的过程如下:

  • 发布Feed

    1. Feed消息先进入一个队列服务。

    2. 先从关注列表中读取到自己的粉丝列表,以及判断自己是否是大V。

    3. 将自己的Feed消息写入个人页Timeline(发件箱)。如果是大V,写入流程到此结束。

    4. 如果是普通用户,还需要将自己的Feed消息写给自己的粉丝,如果有100个粉丝,那么就要写给100个用户,包括Feed内容和Feed ID。

    5. 第三步和第四步可以合并在一起,使用BatchWriteRow接口一次性将多行数据写入表格存储。

    6. 发布Feed的流程结束。

  • 读取Feed

    1. 先读取自己关注的大V列表。

    2. 通过GetRange读取自己的收件箱。范围起始位置是上次读取到的最新FeedID;结束位置可以是当前时间,也可以是MAX,建议是MAX值。

    3. 如果有关注的大V,则再次并发读取每一个大V的发件箱。如果关注了10个大V,那么则需要10次访问。

    4. 合并23步的结果,然后按时间排序,返回给用户。

如果使用大V/普通用户的切分,架构存在一定风险。例如某个大V突然发了一个很有话题性的Feed,那么就有可能导致整个Feed产品中的所有用户都没法读取新内容。以粉丝读取流程为例:

  1. V发送Feed消息。

  2. V使用拉模式。

  3. V的活跃粉丝(用户群A)开始通过拉模式读取大V的新Feed。

  4. Feed内容太有话题性,快速传播。

  5. 未登录的大V粉丝(用户群B)开始登录产品,登录进去后自动刷新,再次通过读3步骤读取大VFeed内容。

  6. 非粉丝(用户群C)去大V的个人页Timeline里面去围观,再次需要读取大V个人的Timeline,同读3。

结果就是,平时正常流量只有用户群A,结果现在却是用户群A + 用户群B + 用户群C,流量增加了好几倍,甚至几十倍,导致读3路径的服务模块被打到server busy或者机器资源被打满,导致读取大V的读3路径无法返回请求。如果Feed产品中的用户都有关注大V,那么基本上所有用户都会卡死在读取大V的读3路径上,然后就没法刷新了。

所以设计时需重点关心下面两点:

  • 单个模块的不可用,不应该阻止整个关键的读Feed流路径。如果大V的无法读取,但是普通用户的要能返回,等服务恢复后,再补齐大V的内容即可。

  • 当模块无法承受这么大流量的时候,模块不应该完全不可服务,而应该能继续提供最大的服务能力,超过的拒绝掉。

优化方法

  • 方法一:不使用大V/普通用户的优化方式,而使用活跃用户/非活跃用户的优化方式,这种优化方式能把用户群A和部分用户群B分流到其他更分散的多个路径上去。而且即使读3路径不可用,仍然对活跃用户无任何影响。

  • 方法二:完全使用推模式可以彻底解决这个问题,但会增大存储量,并增长大V微博发送总时间,从发给第一个粉丝到发给最后一个粉丝可能要几分钟时间(一亿粉丝,100万行每秒,需要100秒),还需要为最大并发预留好资源(如果使用阿里云表格存储,则不需要考虑预留最大额度资源的问题)。

个性化和定向广告

个性化和定向广告是需求度很高的两个功能。个性化可以服务好用户,增大产品竞争力和用户粘性。定向广告可以为产品增加盈利渠道,而且不引起用户反感。在Feed流里这两种功能的实现方式类似,我们以实现定向广告的流程为例来说明。

  1. 通过用户特征分析对用户分类,例如今年刚上大学的新生(新生类)。具体的用户特征分析可以依靠表格存储 + MaxCompute。

  2. 创建一个广告账号:新生广告。

  3. 让这些具有新生特征的用户虚拟关注新生广告账号。用户侧看不到这一层关注关系。

  4. 从七月份开始就通过新生广告账号发送广告。

每个用户可能会有多个特征,那么就可能虚拟关注多个广告账号。

基于推荐的Rank

除了Timeline类型的Feed流类型,Rank类型的Feed流也比较常见。Rank类型的潜在Feed内容非常多,用户无法全部看完,也不需要全部看完,则需要为用户选出最想看的内容。Rank类型典型的应用包括图片分享网站、新闻推荐网站等。

方式一(轻量级)

上面架构图展示的Rank方式比较轻量级,适用于推拉结合的场景。

  • 写流程和Timeline基本一样。

  • 读流程里面会先读取所有的Feed内容,这个和Timeline一样。Timeline中这部分会直接返回给用户,但是Rank类型需要在一个排序模块里面,按照某个属性值排序,然后将所有结果存入一个timeline cache中,并返回分数最高的N个结果,下次读取的时候再返回[N+1, 2N]的结果。

方式二(重量级)

上面架构图展示的Rank方式比较重量级,适用于纯推模式。

  • 写流程和Timeline一样。

  • 每个用户有两个收件箱。

    • 一个是关注页Timeline,保存原始的Feed内容,用户无法直接查看这个收件箱。

    • 一个是rank timeline,保存为用户精选的Feed内容,用户直接查看这个收件箱。

  • 写流程结束后还有一个数据处理的流程。个性化排序系统从原始Feed收件箱中获取到新的Feed内容,按照用户的特征、Feed的特征计算出一个分数。每个Feed在不同用户的Timeline中可能分数不一样的,计算完成后再排序然后写入最终的rank timeline。