设计Twitter时间线和搜索功能

设计Twitter时间线和搜索功能

设计 facebook feed 和 设计 facebook search是相同的问题

第一步:定义用例和约束

定义问题的需求和范围,询问问题去声明用例和约束,讨论假设
ps: 没有一个面试官会展示详细的问题,我们需要定义一些用例和约束

用例:

我们定义问题的范围,只是去处理以下Use Cases

  1. User 发布一个 tweet
  • Service push tweets 给 followers, 发送 push notification 和 email
  1. User 查看这个 user 的 timeline (行为发生来自 user)
  2. User 查看 home 的 timeline (行为发生来自 User follow的人)
  3. User 搜搜关键词
  4. Service 有高可用

问题域外

  1. Service 推送 tweets 到 Twitter Firehose 和其他的 stream
  2. Service 拉取 tweet 基于User的可视化设置
  • 隐藏 @reply 如果这个 User 不能回复被这个人 follow 的人
  • 添加 ‘hide retweets’ 设置
  1. Analystics

约束和假设:

状态假设

  1. 常用
  • Traffic 最终不被分发出去
  • 发布一个 tweet 应该是很快的
  • 发广播给所有的 followers 应该是快的,除非你有数百万的 followers
  • 1000 万活跃用户
  • 5000 万 tweet 每天 或者 150 亿 tweet 每个月
    每条推文的平均传播量为10次
    50 亿个tweet被传播一天
    1500亿tweet被传播每个月
  • 2500 亿个读请求每个月
  • 100 亿搜索每个月
  1. 时间线
  • 展示这个时间线应该很快
  • Twitter是读多写少 (优化为了快速的tweet的Read)
  • Ingesting tweets是写重的
  1. 搜索
  • 搜索应该很快
  • 搜索是读重的

计算使用量:

和面试官说明你是否需要进行粗略使用量估算

  1. 每 tweet 尺寸:
  • tweet_id - 8 bytes
  • user_id - 32 bytes
  • text - 140 bytes
  • media - 10 kb average
  • Total: ~10kb
  1. 每个月有150 TB的新 tweet 内容
  • 10 kb/tweet * 5000 万 tweet / day * 30 天 / 月
  • 三年内会有5.4 PB的新 tweet
  1. 10w read请求 / S
  • 2500 亿读请求每个月 * (400 请求每秒 / 10亿 请求每个月)
  1. 6000 tweets / s
  • 150 亿tweet每个月 * (400 请求每秒 / 10w 请求每个月)
  1. 6w 个 tweet 被广播 / 每秒
  • 1500 亿 tweet 每个月 * (400 请求每秒 / 10 w请求每个月)
  1. 4000 搜索请求每秒
  • 100亿搜索每个月 * (400 请求每秒 / 10 亿请求每个月)

转换规则:
250 万秒每个月
1 request/s = 250 万 request/ 月
40 request/s = 1000 万 request/月
400 request/s = 10 亿 request/月

高视角组件设计

描绘所有重要组件的 high level design

Twitter设计

设计核心组件

Case01: User post a tweet

我们可以存储用户自己的tweet来填充这个用户时间线,我们应该讨论这个用户Case的取舍在SQL和NoSQL之间
传播tweets和构建这个home timeline 是一个笑话,传播tweets给所有的follower(6w tweets delivered on fanout per second) 将 过载一个传统的关系型数据库。我们或许想选择一个数据存储(速度快的写,比如No SQL数据库和内存),从内存中序列化的读1MB数据需要250微秒,当从SSD需要4X,从硬盘中读需要 80X.

我们可以存储媒体文件比如图片和视频在 Object Store

  1. Client 发送一个 tweet 到 Web Server
  2. Web Server 转发这个 request到 Write API server
  3. Write API 存储 tweet 进 SQL 数据库在用户的时间线
  4. Write API 连接 Fan Out Service,会做下面的事情:
  • 使用 User Graph Service去查询这个User的 follower(存储在Cache中)
  • 存储tweet进用户的follower的home timeline(在内存里面)
  • 存储tweet进 Search Index Service,用来开启fast searching
  • 存储 media 进 Object Store
  • 使用 notification service去发送push 的notifications 给 follower
    使用一个 Queue 去异步发送 notifications

向你的面试官说明多少代码你期望去写

如果Cache是使用Redis,我们可以使用原生的Redis List伴随着如下结构:

           tweet n+2                   tweet n+1                   tweet n
| 8 bytes   8 bytes  1 byte | 8 bytes   8 bytes  1 byte | 8 bytes   8 bytes  1 byte |
| tweet_id  user_id  meta   | tweet_id  user_id  meta   | tweet_id  user_id  meta   |

新的 tweet 将会被放进 Memory Cache, 将填充这个User 的 home timeline

我们将使用一个 public REST API:

$ curl -X POST --data '{ "user_id": "123", "auth_token": "ABC123", \
    "status": "hello world!", "media_ids": "ABC987" }' \
    https://twitter.com/api/v1/tweet

Response:

{
    "created_at": "Wed Sep 05 00:37:15 +0000 2012",
    "status": "hello world!",
    "tweet_id": "987",
    "user_id": "123",
    ...
}

内部的服务通信,我们可以使用 Remote Procedure Calls

Case02: User view the home timeline
  1. Client 发送一个 home timeline request 到 Web Server
  2. Web Server 转发请求到 Read API server
  3. Read API server 连接 Timeline Service,会做下面的事情:
  • 得到存储在内存中的timeline数据,包含 tweet ids 和 user ids
  • 查询 Tweet Info Service 去得到额外的喜喜关于 tweet ids
  • 查询 User Info Service去得到额外的信息关于 user ids

REST API:

curl https://twitter.com/api/v1/home_timeline?user_id=123

Response:

{
    "user_id": "456",
    "tweet_id": "123",
    "status": "foo"
},
{
    "user_id": "789",
    "tweet_id": "456",
    "status": "bar"
},
{
    "user_id": "789",
    "tweet_id": "579",
    "status": "baz"
}
Case03: User views the user timeline
  1. Client 发送一个 user timeline request 到 Web Server
  2. Web Server 转发这个 request 到 Read API server
  3. Read API 从SQL 数据库接收 User Timeline

这个 Rest API应该是和 home timeline相同的,除了所有的 tweets应该才子与 User,而不是User 的 follower

Case04: User searches keywords
  1. Client 发送一个 search request 到 Web Server
  2. Web Server 转发 request 到 Search API server
  3. Search API 和 Search Service通信,会做下面的事情:
  • Parses/tokenizes 查询 query,决定什么需要被 search
  • 移除 markup
  • 分解 text 进 terms
  • 修复 typos
  • 格式化首字母
  • 转换query去使用bool操作
  • 查询 Search Cluster(比如 Lucene) 为了结果
  • 去集群中查询 query
  • 合并,排名,排序,然后返回结果

Rest API:

$ curl https://twitter.com/api/v1/search?query=hello+world

扩展设计

开始思考这四件事:

  1. 负载测试
  2. 分析系统瓶颈
  3. 定位瓶颈和分析不同方案和好处
  4. 重复

讨论初始化的Design,定位瓶颈的过程是非常重要的。比如:添加 Load Balancer到多Web Server会产生什么问题? CDN 呢?数据库主从架构呢?什么是最优解?

我么将介绍一些组件来完成这个Design并且去定位扩展性问题,内部的load balancer不被展示去减少
杂乱。

  • DNS
  • CDN
  • Load balancer
  • Horizontal scaling
  • Web server (reverse proxy)
  • API server (application layer)
  • Cache
  • Relational database management system (RDBMS)
  • SQL write master-slave failover
  • Master-slave replication
  • Consistency patterns
  • Availability patterns

分析设计发现,Fanout Service是潜在的瓶颈,Twitter 用户的数百万 follower会花费数分钟来完成广播流程。这可能导致推文 @replies 出现竞争状况,我们可以通过在服务时重新排序堆文件来缓解这种情况。

我们还可以避免将来自高关注度用户的推文散开,代替,我们可以搜索去找到高关注度用户的 tweet,合并搜索结果伴随着用户的 home timeline结果。然后重新排序 tweet 在服务器时间。

额外的优化包括:

  • 保持每个 home timeline只有若百个 tweets 在内存中
  • 保持只有活跃用户的 home timeline info在内存中
    • 如果一个 user 在过去的30天不活跃的化,我们可以从 SQL Database重新构建timeline
      • 查询 User Graph Service 去决定谁是这个 user 正在 following
      • 从数据库获取到 tweets 然后添加他们进内存
  • 只存储一个月的tweets进 Tweet Info Service
  • 只存储活跃用户进 User Info Service
  • Search Cluster 有可能需要保存 tweets 进内存去保证低延迟

我们也想要定位在数据库中的瓶颈。

尽管 Memory Cache 可以减少数据库的负载,仅仅SQL读取副本不足以处理缓存缺失。我们可能需要采用额外的SQL扩展模式。

大量的写入将压倒单个SQL写主从,这也表明需要额外的扩展技术。

  • Federation
  • Sharding
  • Denormalization
  • SQL Tuning

We should also consider moving some data to a NoSQL Database.

Additional talking points

Additional topics to dive into, depending on the problem scope and time remaining.

NoSQL
  • Key-value store
  • Document store
  • Wide column store
  • Graph database
  • SQL vs NoSQL

Caching

  • Where to cache
    • Client caching
    • CDN caching
    • Web server caching
    • Database caching
    • Application caching
  • What to cache
    • Caching at the database query level
    • Caching at the object level
  • When to update the cache
    • Cache-aside
    • Write-through
    • Write-behind (write-back)
    • Refresh ahead

Asynchronism and microservices

  • Message queues
  • Task queues
  • Back pressure
  • Microservices

Communications

  • Discuss tradeoffs:
    • External communication with clients - HTTP APIs following REST
    • Internal communications - RPC
  • Service discovery

Security

Refer to the security section.

Latency numbers

See Latency numbers every programmer should know.

Ongoing

  • Continue benchmarking and monitoring your system to address bottlenecks as they come up
  • Scaling is an iterative process

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/328161.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【软件测试】学习笔记-测试基础架构

这篇文章探讨什么是测试基础架构。 什么是测试基础架构? 测试基础架构指的是,执行测试的过程中用到的所有基础硬件设施以及相关的软件设施。因此,我们也把测试基础架构称之为广义的测试执行环境。通常来讲,测试基础 架构主要包括…

Leetcode23-数组能形成多少数对(2341)

1、题目 给你一个下标从 0 开始的整数数组 nums 。在一步操作中,你可以执行以下步骤: 从 nums 选出 两个 相等的 整数 从 nums 中移除这两个整数,形成一个 数对 请你在 nums 上多次执行此操作直到无法继续执行。 返回一个下标从 0 开始、长…

Spring Security-用户注销及记住我

用户注销 在配置类增加退出映射地址 Overrideprotected void configure(HttpSecurity http) throws Exception {//退出/注销http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();} 完整代码: package com.config;​import o…

礼贺新春,徐坊大曲新品【中国红】

梁山徐坊大曲新推出中国风礼盒,以中国红为主题,为即将到来的新春佳节增添了浓厚的节日气氛。为您呈现一场视觉与味觉的盛宴。从礼盒的颜色到图案设计,无不体现出中国红的热情与活力,象征着吉祥、喜庆与团圆。梁山徐坊大曲&#xf…

设计模式之依赖倒转原则

在软件开发的世界里,设计模式一直是提升代码质量、确保软件稳定性以及优化软件可维护性的重要工具。而在这其中,依赖倒转原则无疑是其中最具代表性的设计模式之一。那么,什么是依赖倒转原则?它又为何如此重要?让我们一…

Android 系统启动过程纪要(基于Android 10)

前言 看过源码的都知道,Launcher系统启动都会经过这三个进程 init ->zygote -> system_server。今天我们就来讲解一下这三个进程以及Launcher系统启动。 init进程 准备Android虚拟机环境:创建和挂载系统文件目录;初始化属性服务&…

解决哈希冲突的几种方法

什么是hash冲突 哈希函数是一个映像,把任意长度的输入,通过Hash算法变换成固定长度的输出,这个输出就是Hash值; 当两个不同的输入,产生了同一个输出值即为哈希冲突 解决方式 开放定址法 开放寻址法的核心思想是&am…

PyQt5多线程使用

PyQt5多线程使用 本案例使用PyQt5多线程实现一个UI界面同时显示3个时间实时更新控件,从而直观地了解到Qt多线程是如何进行工作的。 from PyQt5.QtCore import QThread,pyqtSignal,QDateTime from PyQt5.QtWidgets import QApplication,QDialog,QLineEdit,QVBoxLay…

[Android]实现一个权限申请类

[Android]实现一个权限申请类 导言 在引入了动态权限申请之后,Android的权限申请就变得尤为繁琐,若是按照原有的方法一板一眼地进行申请,样板代码未免太多。因此本篇文章就使用ActivityResult API,来实现一个简单的权限申请类来帮…

【漏洞复现】Kubernetes PPROF内存泄漏漏洞(CVE-2019-11248)

Nx01 产品简介 Kubernetes(简称K8S)是Google在2014年开源的一个容器集群管理系统。它用于容器化应用程序的部署、扩展和管理,目标是让部署容器化应用简单且高效。 Nx02 漏洞描述 漏洞存在于Kubernetes的1.18.6版本之前,可能导致未…

「解析」Jetson配置 git服务

这两天感冒了在家休养,想着把之前买的 Jetson 开发板用起来,买Jetson的初衷就是用来学习Linux系统,顺道可以部署算法,以及一些其他需求,相比树莓派而言,Jetson开发相对更贵,但是其配备了英伟达的…

conda 安装, 配置以及使用

文章目录 1. 安装2. 配置2.1 如何配置2.2 快速设置取消自动进入 base 环境conda 添加清华源pip 添加清华源pip 更新为最新版本 3. 使用 conda 是 python 的环境管理工具包,非常好用,特别是 miniconda 相对于 conda 不需要安装其他的工具,而且…

详细讲解Python中的aioschedule定时任务操作

目录 前言1. 基本概念2. 基本API3. Demo 前言 如果下面的函数库无法执行,出现类似:(前提是python3.7以上) AttributeError: module ‘asyncio‘ has no attribute ‘run‘请检查run是否可跳转,如果无法跳转&#xff…

Jenkins实现基础CI操作配合python

条件: gitlab准备好 jenkins准备好 (不会java项目, 故跳过Maven打jar包) jenkins配置 在配置里通过插件Git Parameter配置Git,以便于从gitlab 拉去代码到Jenkins r容器内 /var/jenkins_home/ 刚接触python 项目好像不需要构建,直接推送到远…

深度学习弱光图像增强入门学习贴及相关可参考工作推荐

0 引言 先表明身份,在过去三年的时间里,发表弱光图像增强的SCI工作多篇,后续会在Github的代码库构建好之后,分享代码链接,欢迎关注(由于工作过于垃圾,因此咱还是以大佬的工作作为参考 首先&am…

推荐一款低成本半桥驱动器集成电路 SIC631CD-T1-GE3

SIC631CD-T1-GE3 是经过优化的集成功率级解决方案用于同步降压应用,提供大电流、高电压效率高,功率密度高。使电压调节器设计能够提供高达50 A的电流每相持续电流。内部功率MOSFET利用Vishay的最先进的第四代TrenchFET技术行业基准绩效将显著降低开关和传…

深入浅出Spring AOP

第1章:引言 大家好,我是小黑,咱们今天要聊的是Java中Spring框架的AOP(面向切面编程)。对于程序员来说,理解AOP对于掌握Spring框架来说是超级关键的。它像是魔法一样,能让咱们在不改变原有代码的…

XSS漏洞:prompt.mi靶场通关

xss系列往期文章: 初识XSS漏洞-CSDN博客 利用XSS漏洞打cookie-CSDN博客 XSS漏洞:xss-labs靶场通关-CSDN博客 目录 第0关 第1关 第2关 第3关 第4关 第5关 第6关 第7关 第8关 第9关 第A关 第B关 第C关 第D关 第E关 第F关 上一篇文章给…

c语言将csv文件中的XY轴数据转换为html波形图

目标: c语言实现一个最简化的csv转html波形图显示方案。 csv文件格式: 共两行数据,第一行是x轴数据,第二行是y轴数据。 csv文件名分为3段: 波形图名称,x轴名称,y轴名称。 c代码: int csv2html…

springboot集成shiro+前端vue,前后端分离项目遇到跨域以及sessionid拿不到等问题

近期在写前后端分离的项目,由于前后端分离导致原来使用的shiro配置无法满足现有系统要求。同时在前后端分离项目中存在的一些问题。例如,一些用户信息需要存储在后端方便进行安全性判断,但这些存储在后端的session前端却获取不到(…