Twitter如何缓存时间线信息?

尝试理解Twitter的内部结构

前方入口

在类似Twitter的微博服务中,用户的发帖数量很大,特别是在时间轴周围,仅仅使用关系型数据库来读写数据已经不能满足大规模需求。

因为在互联网上我发现了一些Twitter员工对于架构进行解释的文章和视频,所以我想总结一下Twitter是如何缓存时间线的(包括猜测)。

推特的表结构

単純なTwitterのテーブル定義をRDBで定義すると以下のようになると思います。

推文

    • id

 

    • user_id

 

    • contents

 

    tweet_at

追随者

    • source_user_id

 

    destination_user_id

用户

    • id

 

    user_name

时间轴

    • user_id

 

    • tweet_id

 

    seq

时间线不仅仅是简单的SQL聚合

在Twitter上,每個用戶都可以發布推文,並可以關注其他用戶。

用户可以在自己的主页时间线上浏览他们关注的人的推文,并且如果进入相关用户的个人资料页面,他们可以浏览用户过去发表的推文列表和用户的时间线。

如果是简单的社交网络服务,你可以使用SQL查询来获取正在关注的用户的ID,并获取指定用户ID在过去某个时间段内发表的推文,这样就可以完成时间线。然而,事情并不那么简单。

如果一个拥有数千名用户关注的人进行汇总统计,会变得很重,并且现实情况下需要进行必要的筛选。另外,还需要满足在主页时间线中插入推荐的推文和广告推文等要求。因此,时间线需要一个单独的表格。

Twitter采用的是PUSH基础架构,当关注的用户发推时,直接写入各个时间线,而不是使用PULL基础架构在获取时进行聚合。

尽管有点偏离这次的主题,但除此之外,貌似还有一些人故意重叠地在关注已关注之人的名单上,并关注着某些人。

在应用程序层上来回切换时间轴是非常昂贵的。

使用Twitter的时候,我认为有时可能会滚到时间线的底部。虽然看起来像是无限滚动,但时间线似乎有一个长度限制。主页时间线可能只能显示300条推文之类的吧。

对于一般用户来说,很少有想要重新呈现一周前的主页时间线的场景。如果想要查看关注的人过去发布的内容,可以通过搜索或查看相关用户的用户时间线来确认。

おすすめや広告などの差込をタイムラインに行うにあたって、差込や入れ替えを愚直にWebアプリのレイヤーでやると

    1. 从时间线表中提取user_id的数据

 

    1. 插入和替换tweet_id并删除

 

    使用事务完全替换timelines表中的user_id数据

我认为会变成。

然而,在像Twitter这样用户数量众多、实时性要求高的服务中,这种操作相对较昂贵。它不是以类似于RDB的高通用性的表结构进行存储,而是利用定制化的Redis上的特殊用途数据结构来表示。

哈普洛(Haplo):在Redis中实现混合列表(Hybrid List)和B-Tree(B树)。

据公开信息,Twitter正在努力将其在内存缓存存储中使用的Memcached+Redis迁移到Pelikan。

除了时间线,Memcached被广泛使用,而时间线则使用Redis。我们自行开发了整合了Memcached和Redis的Pelikan,使得除了时间线外,其他部分都可以相对容易地迁移到Pelikan上。在计划将时间线加入时,负责缓存方面的人似乎已经被解雇了。。。

Pelikan是一个开源项目,最初在GitHub的Twitter下维护,但由于维护者失去权限,所以已经迁移到了pelikan-io。最近有一次在RustConf上发布了关于从C++部分迁移到基于Rust的代码的消息。

时间轴使用的是自定义的Redis,而不是原生Redis,看起来是使用了Haplo。作为数据结构,增加了Hybrid List和BTree。BTree也被用作RDB的索引。

我认为原因可能是,它们将古老版本的Redis进行了分叉,并且可能是因为Redis方面不想设计支持自定义数据结构(尤其是B树)的常规Redis,所以它不支持这些数据结构。

创建混合列表的动机是压缩效率和性能。

时间轴主要使用混合列表进行操作。

Redis是内置的。

    • ziplist

 

    連結リスト

目前支持的有ziplist和连接列表,因此将它们合并称为混合列表,即Hybrid List。

Twitter的时间线基本上是由一系列tweet_id组成的集合。然而,在链表中,它可能有一些不利的结构。如果内容部分相比指针来说足够大的话,我认为可以忽略指针部分,因为tweet_id是一个ID,与指针的差异很小,可能存在优化的空间。

根据我了解,有很多名人在使用自己的简单ziplist时,如果他们的关注者很多,他们的推文会被发布在很多人的时间线上,这可能导致内存不足等问题。

其他表演方面的策略和费用方面的创新。

由于Redis是内存数据存储,因此准备所有注册用户的时间线会增加成本负担。实际上,他们似乎根据最近登录情况来改变缓存策略。

据说在发布推文时,时间线上有个队列,当名人发推文时,时间线更新会出现问题。但是,似乎还有其他缓解此问题的措施。

这片区域的想像成分较多,但是我找到了一个称为”Celebrity Cluster”的视频,如果我当初创建了Twitter的话,可能会给拥有一定数量粉丝的人添加标记,并改变他们进入队列的速度或进行特殊操作。事实上,Twitter每天对关注人数有限制,可能是为了防止突然出现大量的机器人关注名人。

最终、最后、最后的

这个Redis的文档可能有一篇关于如何建立Twitter克隆的文章,尽管有点旧了,但读一读可能也挺有趣的。

我努力阅读了文章和观看了视频,但可能会有一些遗漏,如果有错误,请指正。

请参考以下资源。

Scaling Redis at Twitter, 2014

“Cache à la carte: a framework for in-memory caching” by Yao Yue, 2015

Using Redis at Scale at Twitter – by Rashmi Ramesh of Twitter – RedisConf17 -, 2017
RustConf 2021 – Whoops! I Rewrote It in Rust by Brian Martin
Pelikan
Timelines at Scale
Real-Time Delivery Architecture at Twitter

广告
将在 10 秒后关闭
bannerAds