设计 Pastebin.com

设计 Pastebin.com

设计 Bit.ly 是一个类似的问题,区别是 pastebin 需要存储的是 paste 的内容,而不是原始的未短化的 url.

怎么处理这个问题?

第一步:概述用例和约束

收集这个问题的需求和范畴。问相关问题来明确用例和约束,讨论一些假设。

我们把问题的范畴定在如下用例:

  1. 用户输入一段文本,然后得到一个随机生成的链接
  • 过期设置
    默认的设置是不会过期的
    可以选择设置一个过期的时间
  1. 用户输入一个 paste 的 url 后,可以看到它存储的内容
  2. 用户是匿名的
  3. Service 跟踪页面分析
  • 一个月的访问统计
  1. Service 删除过期的 pastes
  2. Service 需要高可用

超出范畴的用例:

  1. 用户可以注册一个账户
  • 用户通过验证邮箱
  1. 用户可以用注册的账户登录
  • 用户可以编辑文档
  1. 用户可以设置可见性
  2. 用户可以设置短链接

约束和假设

状态假设

  1. 访问流量不是均匀分布的
  2. 打开一个短链接应该是很快的
  3. pastes 只能是文本
  4. 页面访问分析数据可以不用实时
  5. 一千万的用户量
  6. 每个月一千万的 paste 写入量
  7. 每个月一亿的 paste 读取量
  8. 读写比例在 10:1

计算使用
向面试官说明你是否应该粗略计算一下使用情况

  1. 每个 paste 的大小
  • 每一个 paste 1 kb
  • shortlink - 7 bytes
  • expiration_length_in_minutes - 4 bytes
  • created_at - 5 bytes
  • paste_path - 255 bytes
    总共 = ~1.27 kb
  1. 每个月新的 paste 内容在12.7 GB
  • (1.27 * 10000000) kb / 月的 paste
  • 三年将近 450 GB 的新 paste 内容
  • 三年内 3.6 亿短链接
  • 假设大部分都是新的 paste, 而不是需要更新已存在的 paste
  1. 平均 4 paste/s 的写入速度
  2. 平均 40 paste/s 的读取速度

简单的转换指南:

2.5 百万 req/s
1 req/s = 2.5 百万 req/m
40 req/s = 1 亿 req/m
400 req/s = 10 亿 req/m

第二步:创建一个高层次设计

概述一个包括所有重要的组件的高层次设计

高层次设计

第三步:设计核心组件

深入每一个核心组件的细节

用例:用户输入一段文本,然后得到一个随机生成的链接

我们可以用一个 关系型数据库 作为一个大的哈希表,用来把生成的 url 映射到一个包含 paste 文件的文件服务器和路径上。
为了避免托管一个文件服务器,我们可以用一个拖管的对象存储,比如 Amazon 的 S3 或者 NoSQL文档类型存储。
作为一个大的哈希表的关系型数据库的替代方案,我们可以用 NoSQL键值存储。我们需要讨论选择 SQL 和 NoSQL 之间的权衡。

  • 客户端发送一个创建 paste 的请求到作为一个反向代理启动的服务器
  • Web 服务器转发请求给写接口服务器
  • 写接口服务器执行如下操作:
  1. 生成一个唯一的 url
  • 检查这个 url 在 SQL 数据库里面是否唯一
  • 如果这个 url 不是唯一的,生成另外一个 url
  • 如果我们支持自定义 url,我们可以使用用户提供的 url
  1. 把生成的 url 存储到 SQL 数据库的 pastes 表中
  2. 存储 paste 的内容数据到对象存储中
  3. 返回生成的 url

向面试官阐明你需要写多少代码

paste 表可以有如下结构:

shortlink char(7) NOT NULL
expiration_length_in_minutes int NOT NULL
created_at datetime NOT NULL
paste_path varchar(255) NOT NULL
PRIMARY KEY(shortlink)

我们将在 shortlink 字段和 created_at 字段上创建一个数据库索引,用来提高查询的速度(避免因为扫描全表导致的长时间查询)并将数据保存到内存中,从内存里面顺序读取 1MB 的数据需要大概 250 微秒,而从 SSD 上读取则需要花费 4 倍的时间,从磁盘上则需要花费 80 倍的时间。

为了生成唯一的 url, 我们可以:

  1. 使用 MD5 来哈希用户的 IP 地址 + 时间戳
  • MD5 是一个普遍用来生成一个 128 bit长度的hash值的一种hash办法
  • MD5 是一致分布的
  • 或者我们也可以用MD5 哈希一个随机生成的数据
  1. 用 Base 62编码 MD5 哈希值
  • 对于 urls,使用 Base 62编码[a-zA-Z0-9]是比较合适的
  • 对于每一个原始输入只会有一个 hash 结果, Base62是不确定的
  • Base 64 是另外一个流行的编码方案,但是对于 urls,会因为额外的 + 和 - 字符串而产生一些问题
def base_encode(num, base=62):digits = []while num > 0remainder = modulo(num, base)digits.push(remainder)num = divide(num, base)digits = digits.reverse

取输出的前7个字符,结果会有63*7个可能的值,应该足以满足在3年内处理3.6亿个短视频的约束:

url = base_encode(md5(ip_address+timestamp))[:URL_LENGTH]

我们将会用一个公开的 REST 风格接口:

curl -X POST --data '{"expiration_length_in_minutes":"60",\"paste_contents":"Hello World"}' https://pastebin.com/api/v1/paste

于内部通信,我们可以用 RPC。

用例:用户输入一个 paste 的 url 后可以看到它存储的内容

  • 客户端 发送一个获取 paste 请求到 Web Server
  • Web Server 转发请求给 读取接口 服务器
  • 读取接口 服务器执行如下操作:
    • SQL 数据库 检查这个生成的 url
      • 如果这个 url 在 SQL 数据库 里面,则从 对象存储 获取这个 paste 的内容
      • 否则,返回一个错误页面给用户

REST API:

curl https://pastebin.com/api/v1/paste?shortlink=foobar

Response:

{"paste_contents": "Hello World","created_at": "YYYY-MM-DD HH:MM:SS","expiration_length_in_minutes": "60"
}

用例: 服务跟踪分析页面

因为实时分析不是必须的,所以我们可以简单的 MapReduce Web Server 的日志,用来生成点击次数。

class HitCounts(MRJob):def extract_url(self, line):"""Extract the generated url from the log line."""...def extract_year_month(self, line):"""Return the year and month portions of the timestamp."""...def mapper(self, _, line):"""Parse each log line, extract and transform relevant lines.Emit key value pairs of the form:(2016-01, url0), 1(2016-01, url0), 1(2016-01, url1), 1"""url = self.extract_url(line)period = self.extract_year_month(line)yield (period, url), 1def reducer(self, key, values):"""Sum values for each key.(2016-01, url0), 2(2016-01, url1), 1"""yield key, sum(values)

用例: 服务删除过期的 pastes

为了删除过期的 pastes,我们可以直接搜索 SQL 数据库 中所有的过期时间比当前时间更早的记录,
所有过期的记录将从这张表里面删除(或者将其标记为过期)。

第四步:扩展这个设计

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github 2024-01-16 Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-01-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10HTML项目1 精心策划的Python资源列表 创建周期:3490 天开发语言:Python…

蓝桥杯备赛 | 洛谷做题打卡day3

蓝桥杯备赛 | 洛谷做题打卡day3 sort函数真的很厉害! 文章目录 蓝桥杯备赛 | 洛谷做题打卡day3sort函数真的很厉害!【深基9.例1】选举学生会题目描述输入格式输出格式样例 #1样例输入 #1 样例输出 #1 我的一些话 【深基9.例1】选举学生会 题目描述 学校…

23111 网络编程 day2

思维导图 重打代码 #include<myhead.h> #define SER_IP "192.168.122.150" //服务器ip #define SER_PORT 8888 //服务器端口int main(int argc, const char *argv[]) {//1.创建用于连接的套接字int sfdsocket(AF_INET,SOCK_STREAM,0);if(sfd-1){perror("…

Python - 深夜数据结构与算法之 位运算

目录 一.引言 二.位运算简介 1.二进制与十进制 2.左/右移 3.位运算 4.异或 XOR 5.指定位置的位运算 6.实战要点 三.经典算法实战 1.Number-1-of-bits [191] 2.Power-Of-Two [231] 3.Reverse-2-Bits [190] 4.N-Queens [51] 四.总结 一.引言 通常情况下我们计数采…

Flink-SQL——时态表(Temporal Table)

时态表(Temporal Table) 文章目录 时态表(Temporal Table)数据库时态表的实现逻辑时态表的实现原理时态表的查询实现时态表的意义 Flink中的时态表设计初衷产品价格的例子——时态表汇率的例子——普通表 声明版本表声明版本视图声明普通表 一个完整的例子测试数据代码实现测试…

使用Github + PicGo搭建个人图床,并使用CDN加速

文章目录 前言创建仓库配置PicGo如何使用 前言 在写博客的时候&#xff0c;常常需要为博客配图&#xff0c;于是一个好用稳定的图床的重要性不言而喻。本文主要介绍如何使用GitHub PicGo的方式快速搭建一个个人使用的图床。该方式方便快捷&#xff0c;还免费hh&#xff0c;唯…

python 集合的详细用法

当前版本&#xff1a; Python 3.8.4 简介 Python中的集合是一种无序、可哈希的且不重复的数据类型&#xff0c;用于存储唯一的元素。集合的实现基于哈希表&#xff0c;因此在插入、查找和删除元素时具有高效性能。集合的每个元素都必须是不可变的&#xff0c;可以是数字、字符…

瑞_Java开发手册_(二)异常日志

文章目录 异常日志的意义(一) 错误码(二) 异常处理(三) 日志规约附&#xff1a;错误码列表 &#x1f64a;前言&#xff1a;本文章为瑞_系列专栏之《Java开发手册》的异常日志篇&#xff0c;本篇章主要介绍异常日志的错误码、异常处理、日志规约。由于博主是从阿里的《Java开发手…

基于Redis+Lua的分布式限流

本文已收录至我的个人网站&#xff1a;程序员波特&#xff0c;主要记录Java相关技术系列教程&#xff0c;共享电子书、Java学习路线、视频教程、简历模板和面试题等学习资源&#xff0c;让想要学习的你&#xff0c;不再迷茫。 前面我们了解了如何利用Nginx做网关层限流&#xf…

Microsoft Remote Desktop for Mac 中文正式版下载 微软远程连接软件

Microsoft Remote Desktop 是一款专为 Mac 用户设计的远程桌面工具&#xff0c;它可以帮助用户通过网络连接到其他计算机&#xff0c;实现远程控制和操作。 软件下载&#xff1a;Microsoft Remote Desktop for Mac 中文正式版下载 该工具支持多种远程连接协议&#xff0c;包括 …

【数学建模美赛M奖速成系列】数据可视化方法(一)

数据可视化方法 写在前面山脊图优点缺点实现matlabpython 气泡矩阵图实现matlabpython 后续 写在前面 最近开始更新一个新的系列科研绘图&#xff0c;在同一个竞赛下&#xff0c;大家都近乎相同的解题思路下。之所以能出现一等二等三等奖的区别很大部分都在于结果的可视化&…

Docker 容器之间的互相通信

Docker容器之间的互相通信 步骤一&#xff1a;创建自定义网络 首先&#xff0c;我们需要创建一个自定义网络&#xff0c;以便容器可以连接到这个网络上&#xff0c;从而实现互相通信。在命令行中执行以下命令&#xff1a; # 创建 docker network create ddz # 查看 docker n…

利用Socket动手实现简单HTTP协议

☆* o(≧▽≦)o *☆嗨~我是小奥&#x1f379; &#x1f4c4;&#x1f4c4;&#x1f4c4;个人博客&#xff1a;小奥的博客 &#x1f4c4;&#x1f4c4;&#x1f4c4;CSDN&#xff1a;个人CSDN &#x1f4d9;&#x1f4d9;&#x1f4d9;Github&#xff1a;传送门 &#x1f4c5;&a…

python 元组的详细用法

当前版本&#xff1a; Python 3.8.4 文章目录如下 1. 介绍元组 2. 定义元组 3. 访问元组 4. 查询元组 1. 介绍元组 元组&#xff08;Tuple&#xff09;是一个有序的、不可变的数据序列。它可以包含各种类型的数据&#xff0c;例如数字、字符串、列表等。元组使用圆括号()来…

Elasticsearch:聊天机器人教程(二)

这是继上一篇文章 “Elasticsearch&#xff1a;聊天机器人教程&#xff08;一&#xff09;”的续篇。本教程的这一部分讨论聊天机器人实现中最有趣的方面&#xff0c;以帮助你理解它并对其进行自定义。 数据摄入 在此应用程序中&#xff0c;所有示例文档的摄取都是通过 flask …

2024年信息安全不完全预测

不需要专家预言就能知道&#xff0c;计算机安全将在2024年出现在新闻中&#xff0c;而且可能不是什么好事。但2024年网络犯罪分子将如何试图突破防御并窃取有价值的数据&#xff0c;值得我们看一看安全专家们的看法和预测。 不需要专家预言就能知道&#xff0c;计算机安全将在…

【深度学习I-基础知识】

深度学习I-基础知识 1 基础知识1.1 模型的基本概念1.2 机器学习1.2.1 概率建模1.2.2 核方法1.2.3 决策树、随机森林和梯度提升机 1.3 深度学习1.3.1 张量1.3.2 数据批量1.3.3 张量运算1.3.4 训练过程 1 基础知识 1.1 模型的基本概念 模型是现实世界中一类具有泛化共性的真实系…

canvas截取视频图像(图文示例)

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

2023一带一路暨金砖国家技能发展与技术创新大赛“网络安全”赛项省选拔赛样题卷②

2023金砖国家职业技能竞赛"网络安全" 赛项省赛选拔赛样题 2023金砖国家职业技能竞赛 省赛选拔赛样题第一阶段&#xff1a;职业素养与理论技能项目1. 职业素养项目1. 职业素养项目2. 网络安全项目3. 安全运营 第二阶段&#xff1a;安全运营项目1. 操作系统安全配置与加…

Docker部署的gitlab升级指南(15.11.X容器里升级PostgreSQL到13.8)

一、确定当前版本 #进入当前版本容器产看gitlab版本 docker exec -it gitlab cat /opt/gitlab/embedded/service/gitlab-rails/VERSION#显示版本如下 14.4.0二、备份数据&#xff0c;防止升级发生意外 #执行备份命令 docker exec -ti gitlab gitlab-rake gitlab:backup:creat…