Feed流系统
<p>[TOC]</p>
<h1>概述</h1>
<p>微博、抖音、朋友圈等等</p>
<h1>架构</h1>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=59a3991dd1a40bfefade8be3478f853b&file=file.png" alt="" /></p>
<h1>说明</h1>
<ul>
<li>Feed 流系统中,有两种常见的模式,一种是 push,一种是 pull。基本上,对于用户的 “被关注用户”(粉丝)可能远大于 “关注用户” 的系统,比如 Twitter,pull model 是必选,push 是可选;反之,特别是对于一些用户关系要求必须双向的,比如朋友圈,往往不会有很多的 “粉丝”,那就可以将 push 作为主要模式。无论如何,pull 和 push 有利必有弊,如果结合使用,可以根据场景来选择,看似很美,可又会增加系统的复杂性。这里按照二者结合的设计来叙述。</li>
<li>这里提给 push 和 pull 各提一个经典问题:
<ul>
<li>第一个问题是 push 模型下,由于粉丝众多,推文占用容量过大的问题,一种解决思路是在粉丝的时间线中只存储推文 id,但是这样的话在聚合的时候需要一次额外的根据推文 id 去获取推文的 I/O;另一种解决思路是只给活跃用户 push。</li>
<li>第二个问题是 pull 模型下,突然某个大 V 的某一话题活了起来,大量的用户访问该推文,导致所在机器顶不住了(这也是新浪微博挂掉的常见原因)。这个也没有太好的解决办法,可以考虑对于特别火爆的推文拉出专门的一层缓存来扛流量,另外要有流控,丢掉部分请求,尽最大能力服务。</li>
</ul></li>
<li>首先,用户本身的数据,存放在 User DB 里,和很多其它系统一样,它可以是一个关系数据库。但是用户的关联关系,可以单独存放,它可以使用关系数据库,也可以使用 Graph DB。</li>
<li>右侧的 Tweet Storage:用户和帖子(推文)的关联数据,数据量会比较大,可以选择 Redis 这样的 KV 数据库;而推文本身,也可以使用 KV 数据库,或者使用 MongoDB 这一类文档数据库,以适应弱结构化文本为主的数据。但是,Twitter 和微博都使用了 MySQL 来存放这类数据,并且 Twitter 给 MySQL 做了相当的优化,这里面不只有技术原因,更多的还有历史原因。</li>
<li>关于对推文的 Sharding,这是一个 Feed 系统的核心话题。
<ul>
<li>一种方式是根据时间的范围来划分,这也是 Twitter 早期的做法,这种做法有一个严重的问题,就是老的推文没有人看,而新推文则火得不得了,因此机器的 load 严重不均。</li>
<li>第二种方式是根据推文的 id 来做简单 hash,这种方式最大的问题是一个人的推文可能分散到任何一台机器上,为了找这个人的推文要去所有的机器上查询并聚合(既包括网络 I/O,也包括磁盘 I/O),这无疑是过于浪费了。</li>
<li>第三种方式是根据用户 id 来做 hash,保证某一个特定用户的推文只存储在同一台机器上,但这个方式有两个问题,(1)有时候某特定几个用户会火,导致 load 不均,这种情况需要用良好设计的 Cache 来缓和;(2)某些用户发推多而某些用户少,因此时间长了 shards 的容量使用差异可能很大,这需要一个改进的找 shard 的路由算法。</li>
</ul></li>
<li>Media Storage,用于存放图像等媒体数据,这可以是一个 “单纯” 的分布式文件系统,比如 HDFS。</li>
<li>用户推文的时候,根据用户所应对的策略,如果需要 fan out 推文的 id 到粉丝的时间线中,就要把这个事件进 queue,由于它是异步模型,这一步可能会有不同程度的延迟。</li>
<li>在用户读取的时候,缓存是非常重要的,考虑到需要的容量巨大,为了增加命中率,减少冗余的缓存信息,可以使用集中式缓存集群。</li>
<li>Aggregation Service 是用来从多个存储节点中为某个用户拉取数据(pull 模型),合并时间线,并返回的。为了提高效率,这里是多个并行拉取,再聚合的。这些数据可能是即时拉取的(pull 模型),也可能是已经,或者部分已经在之前的 Fan-out 流程中写入存储而准备好了的(push 模型)。
<h1>参考资料</h1>
<p><a href="https://zhuanlan.zhihu.com/p/30226315">https://zhuanlan.zhihu.com/p/30226315</a>
<a href="https://cloud.tencent.com/developer/article/1744756">https://cloud.tencent.com/developer/article/1744756</a></p></li>
</ul>