如何设计Twitter的系统(系统设计)

第一步:确定需求

先确定功能性的需求点

  1. 发twitter
  2. 转发twitter
  3. 点击关注
  4. 搜索功能

其次是非功能性的需求

  1. twitter平台属于高频率的读操作平台,twitter的读写比很高(相比写操作,读操作的频率非常高),设计模式需要考虑这点
  2. 页面可以快速渲染
  3. 支持快速发布twitter
  4. 可接受一定的延迟,注意这里的延迟是指可以允许获取关注人的动态数据的延迟,不是页面渲染的延迟
  5. 高并发,twitter平均每天每秒会发布5k左右的推文, 加上高频率的读取操作,并发量是成倍增加的,系统必须支持很高的QPS(Query per second)

第二步:确定用户群体

说明:将我们的用户进行类别划分,不同的用户采取不同的实现方式

  1. 名人:包括法政界、商界、娱乐圈、体育名人,该人群的特点是被广泛关注
  2. 活跃用户:近期使用过系统,比如近三天登录过系统的用户可划分为活跃用户
  3. 在线用户:当前正在使用系统的用户
  4. 非活跃用户:拥有账号,但是近三天没有用过系统
  5. 僵尸用户:被逻辑删除了的用户(不是实际删除),相当于用户不存在了

第三步: 系统架构
说明:下图是整个twitter系统架构,由于存在高并发以及读操作频繁的情况,我们需要很大程度上用到缓存机制。

在这里插入图片描述

第四步:3大工作流
说明:这里主要以service层的功能来进行阐述,每个工作流可能涉及多个service以及service相互调用的情况。

1. 首页工作流:

  • service: user service
  • 主要功能有查看和存储用户个人信息,提供登录和注册服务
  • 数据存储采用mysql数据库+redis(因为用户数量是在可控范围,并且存在关联,比较适合用mysql,redis可以提供缓存,减少数据库读取的压力)

2. 用户关注工作流:

  • Graph Service:点击“关注”动作可以用图结构,所有用户就如同图结构中的节点,相互关联。Graph Service包含所有跟关注相关的实现。
  • 通过api传参user_id获取关注人,或者通过api传参user_id获取被关注人
  • 数据存储依然采用mysql数据库+redis。关联的关系比较稳定,不会经常变动,所以采用redis再合适不过。缓存存储信息可分为两部分:某个人的关注人和被关注人。
  • Analytics Service:我们可以将用户之间的互动操作数据,导入到kafka进行实时数据操作。Analytics Service中实现这种触发动作
  • User Live Websocket service:在线用户可以即时获取关注人的动态信息,采用websocket技术,服务期和所有在线用户建立一个开放的网路通道,当用户所关注的人有新消息时,可以立即收到信息。
    用户的行为数据,也将同步到kafka进行数据分析。比如用在线时长和在线时间段等。并将用户最后的活跃时间保存到redis, 或供其他系统使用。

3. twitter工作流

  • Asset service: 用户可发送推文或者查看推文,推文内容可包含文字、图片、视频或链接。
    推文长度控制再140字,因此我们需要将URL转换成短链接以节省空间。
  • Tweet ingestion service: 不对外提供api, 主要功能就是提交tweet后的一系列操作。将数据同步到kafka
  • Tweet Service: 用户可通过user_id/tweet_id来获取推文内容
  • **Tweet processor:**用户主页有一个展示自己动态的时间线,或者可查看所关注的人的推文的时间线,如果一次性进行获取,页面渲染速度将会非常慢。所以采用缓存技术,提前计算活跃用户的时间线并存储到redis, 这样活跃用户可及时获取时间线。
  • Timeline Service :
    针对活跃用户:我们在redis中缓存他的时间线内容。比如说U1被U2,U3所关注,当U1发布新推文,那么通过图结构找到U1的关注者,并同步在缓存中更新他们的时间线。U1自身的时间线也在缓存中得到更新。
    针对不活跃用户:比如P1用户登录了,系统将到user Service提取P1的关注人列表数据,再到tweet service获取关注人的推文时间线,存到缓存中,最后将数据返给用户
    针对在线用户:通过创建的websocket,通知用户最新的时间线消息
    名人用户:假如美国总统川普发了一个推文,如果按照活跃用户的方法去更新,系统操作量非常庞大。所以Timeline service从graph service获取当前用户所关注的名人列表,并从tweet service获取名人推文,然后在redis中进行更新并添加时间戳。当用户下次请求的时候,会先在redis中检查时间戳是否最新,最新的话就直接redis中读取,否则从tweet service获取。
    被名人关注的名人用户:听起来有点绕口,我们举个例子,比如美国总统川普和马斯克相互关注,如果川普更新推文,那么关注他的名人马斯克必须优先被通知。同样利用tweet processor方法,该方法接收到kafka的关于川普的推文,那么就会更新关注川普的名人的缓存。但该方法也有瓶颈,Cassandra会面临巨大的负载,Redis需要高效地扩容,所以我们需要确保这些组件支持水平扩容,并且redis避免存储老数据,避免占用内存空间;
  • Search Service
    上面我们提过tweet ingestion service,当创建了一条推文,kafka将被触发,推文被存储到Elasticsearch数据库。当用户开始搜索时,Search Service会到elasticsearch获取数据,并返回用户。
    具体流程:一条热搜的推文,将会有很多人进行搜索,当search service从elasticsearch获取结果后,会将它存储到redis,并保留2-3分钟,这样用户搜索时会首先查看redis,如果没有则search service从
    elasticsearch获取。
  • Trend Service: 热搜排名,kafka会分析出热搜关键词,并在用户侧进行展示,这些热搜词不需要进行永久存储,我们采用Redis进行短期存储。可以看到Redis在我们系统中占据重要的位置,但redis是内存存储方式,因此我们需要将数据持久化,确保系统故障时数据可恢复。

下图是twitter工作流所涉及的service层之间的关联图,结合文字描述,值得细细品味~

在这里插入图片描述

以上,如果你能在系统设计面试中呈现出如上这样的逻辑,那么基本上面试过关就没什么问题了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值