聊聊Twitter的架构决策
Twitter有两条时间线:
-
用户时间线: 用户自己所有推文的集合,从磁盘中获取。
-
主页时间线: 用户关注的人的推文的集合,组成了用户的主页。
在设计数据库时,最简单的数据库只是将所有写操作附加到文件的末尾,并在需要时读取。没有什么比简单的附加到文件中更快的了,但是,随着数据库文件的增长,从这种类型的数据库中查询某些内容将花费很长时间。
为了减少查询时间,我们在其中添加索引。但是添加索引将意味着写入将花费更长的时间,因为必须在将其写入数据库之前编辑索引。但由于读取的数量将远远多于写入的数量,这是一种公平的权衡。
同样,Twitter的阅读量也远远超过了写入量。所以他们构建了一个系统,可以更好的为用户的主页时间线服务。他们预先计算出所有用户的主页时间线,并将其存储在Redis集群中。就这么简单!
现在,无论用户何时发布消息,该消息都会被插入每个关注者的时间线队列中。所以如果你有5000个粉丝,你的推文就会有5000个写操作!外加上1个数据库本身的写操作
这听起来很疯狂,但你仔细想想,这是有道理的。现在可以同时为数百万用户提供服务而不需要访问磁盘,这可以从根本上减少延迟。这个过程叫做扇出(fan-out)!
-
那么到目前为止,Twitter的架构是怎样的呢?
-
用户访问Twitter的主页。
-
Twitter在Redis集群中查找用户的主页时间线。
-
一旦找到,就向用户直接展示。
当用户发送一条推文时,该推文会被复制到用户的所有关注者的时间线上。
还有一些其他的细节:
-
Twitter维护了一个图数据库,其保存了用户关注关系的所有数据。当发生扇出时,扇出服务查询这个图数据库以确定将推文推送到何处。
-
扇出将在数据中心的3台不同的机器上进行复制,即每个用户的时间线存储在3台不同的机器上。这是必需的,因为如果其中一台机器出现故障,其他机器可以作为备份提供服务。
-
推文本身并不存储在集群中,而只存储推文ID。推文将在传递给用户的同时被检索出来。
-
如果用户超过30天没有登录Twitter,该用户的时间线将不会保存在Redis集群中。对于这类用户,只有当他们返回并向主页时间线发出请求时,才会从磁盘重构他们的时间线。
每个用户的主页时间线上存储的推文数量是有限制的,每次只向用户显示800条推文,这是为了控制内存使用而做出的设计决策!