Pastebin设计之旅:从零设计网络文本存储系统

这篇具有很好参考价值的文章主要介绍了Pastebin设计之旅:从零设计网络文本存储系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目简介:Pastebin是一个在线的文本存储平台,让用户可以存储和分享代码片段或者其他类型的文本。它支持多种编程和标记语言的语法高亮,用户可以选择让他们的"paste"公开或私有。无需注册就可以使用,但注册用户可以更方便地管理他们的"paste"。Pastebin常被开发者、系统管理员以及其他技术专业人员用于分享和协作。

现在让我们来设计一个类似Pastebin的网络服务,用户可以在这里储存纯文本。用户可以输入一段文本,并获取一个随机生成的URL来访问这段文本。

类似的产品有:pastebin.com,controlc.com,hastebin.com,privatebin.net

系统难度等级:初级

1、什么是Pastebin

Pastebin及类似服务让用户能够在网络(通常指的是互联网)上存储纯文本或图像,并生成唯一的URL来访问上传的数据。这样的服务也被用来快速地在网络上共享数据,用户只需传递URL,其他用户就可以查看其内容。

如果你以前没有使用过pastebin.com,建议尝试在那里创建一个新的“Paste”,并花些时间浏览他们服务提供的不同选项。这将在理解本章时有很大帮助。

对于类似于Pastebin这样的代码或文本分享平台,中国并未有一款特别知名或广泛使用的网站。很多开发者会使用GitHub Gist来分享代码片段,此外,国内也有一些代码托管平台,比如Coding.net和Gitee,也提供代码分享和协作的功能。

2、系统的需求和目标

Pastebin服务需要满足以下要求:

功能需求

  1. 用户应能够上传或“粘贴”他们的数据,并获得一个独特的URL来访问它。
  2. 用户只能上传文本。
  3. 数据和链接将在特定的时间段后自动过期;用户应可以指定过期时间。
  4. 用户可以选择为他们的粘贴内容设置一个自定义的别名。

非功能性需求

  1. 系统必须具有高度的可靠性,上传的任何数据都不应丢失。
  2. 系统必须始终可用。这是因为如果我们的服务暂停,用户将无法访问他们的粘贴内容。
  3. 用户应能实时访问他们的粘贴内容,延迟要最小。
  4. 粘贴的链接不能被轻易猜出(不能被预测)。

扩展需求

  1. 分析,例如,一个粘贴内容被访问了多少次?
  2. 我们的服务也应该通过REST APIs供其他服务访问。

3、注意事项

Pastebin与URL缩短服务(系统设计上一个案例)有一些相同的需求,但是我们还应该考虑一些额外的设计因素。

用户每次粘贴的文本量应有何限制?我们可以限制用户不得粘贴超过 10 M B 10MB 10MB的数据,以防止服务被滥用。

我们是否应对自定义**URL**的大小设置限制?由于我们的服务支持自定义URL,用户可以选择他们喜欢的任何URL,但是提供自定义URL并非强制性的。然而,对自定义URL设置大小限制是合理的(而且通常是我们期望的),这样我们可以保持一致的URL数据库。

4、容量估计与约束

我们的服务将是读取密集型的;相比新建Paste,读取请求会更多。我们可以假设读取与写入之间的比例是 5 : 1 5:1 5:1

流量预估:Pastebin类似的服务并不预期有如微信或今日头条那样的流量,这里我们假设每天有一百万个新的粘贴内容添加到我们的系统中。这样算来,我们每天有五百万次的读取。

每秒新粘贴内容

1 M / ( 24 小时 ∗ 3600 秒 )   = 12 粘贴 / 秒 1M / (24 小时 * 3600 秒) ~= 12 粘贴/秒 1M/(24小时3600) =12粘贴/

每秒粘贴读取次数

5 M / ( 24 小时 ∗ 3600 秒 )   = 58 读取 / 秒 5M / (24 小时 * 3600 秒) ~= 58 读取/秒 5M/(24小时3600) =58读取/

存储预估:用户最多可以上传 10 M B 10MB 10MB的数据;一般来说,Pastebin类似的服务用于分享源代码、配置文件或日志。这些文本并不大,所以我们假设每个粘贴内容平均含有 10 K B 10KB 10KB

按照这个速率,我们每天将存储 10 G B 10GB 10GB的数据。

1 M ∗ 10 K B = > 10 G B / 天 1M * 10KB => 10 GB/天 1M10KB=>10GB/

如果我们想将这些数据存储十年,那我们总共需要 36 T B 36TB 36TB的存储容量。

每天有 1 M 1M 1M的粘贴内容,十年后我们将有36亿的粘贴内容。我们需要生成并存储键来唯一地标识这些粘贴内容。如果我们使用Base64编码([A-Z, a-z, 0-9, ., -]),我们将需要六个字符的字符串:

6 4 6   = 68.7 亿个唯一字符串 64^6 ~= 68.7亿个唯一字符串 646 =68.7亿个唯一字符串

如果存储一个字符需要一个字节,存储 36 亿 36亿 36亿个键所需的总大小将是:

3.6 B ∗ 6 = > 22 G B 3.6B * 6 => 22 GB 3.6B6=>22GB

相比于 36 T B 36TB 36TB 22 G B 22GB 22GB微不足道。为了保留一些余量,我们将假设一个70%的容量模型(意味着我们在任何时候都不希望使用超过总存储容量的70%),这将使我们的存储需求增加到 51.4 T B 51.4TB 51.4TB

带宽预估:对于写入请求,我们预计每秒新增12个粘贴内容,导致每秒进入 120 K B 120KB 120KB的数据。

12 ∗ 10 K B = > 120 K B / s 12 * 10KB => 120 KB/s 1210KB=>120KB/s

至于读取请求,我们预计每秒58个请求。因此,总的数据出口(发送给用户)将是 0.6 M B / s 0.6 MB/s 0.6MB/s

58 ∗ 10 K B = > 0.6 M B / s 58 * 10KB => 0.6 MB/s 5810KB=>0.6MB/s

尽管总的进出口并不大,我们在设计服务时应记住这些数字。

内存预估:我们可以缓存一些被频繁访问的热门粘贴内容。根据80-20原则,意味着20%的热门粘贴内容产生了80%的流量,我们希望将这20%的粘贴内容进行缓存。

既然我们每天有500万次的读取请求,要缓存这些请求中的20%,我们需要:

0.2 ∗ 5 M ∗ 10 K B   = 10 G B 0.2 * 5M * 10KB ~= 10 GB 0.25M10KB =10GB

因此,我们大约需要 10 G B 10GB 10GB的内存来缓存那些热门的粘贴内容。

5、系统API

我们可以有SOAPREST API来公开我们服务的功能。以下是创建/检索/删除粘贴内容的API定义:

addPaste(api_dev_key, paste_data, custom_url=None user_name=None, paste_name=None, expire_date=None)

参数

api_dev_key (字符串): 已注册帐户的API开发者密钥。这将用于基于分配的配额对用户进行限流等操作。

paste_data (字符串): 粘贴的文本数据。

custom_url (字符串): 可选的自定义URL

user_name (字符串): 可选的用于生成URL的用户名。

paste_name (字符串): 粘贴内容的可选名称。

expire_date (字符串): 粘贴内容的可选过期日期。

返回: (字符串)

成功插入返回可以访问粘贴内容的URL,否则,它将返回一个错误码。

类似地,我们可以有检索和删除粘贴内容的API:

getPaste(api_dev_key, api_paste_key) 

其中api_paste_key是一个表示要检索的粘贴内容的粘贴键的字符串。这个API将返回粘贴内容的文本数据。

deletePaste(api_dev_key, api_paste_key) 

成功删除返回true,否则返回false

6、数据库设计

关于我们存储的数据性质,我们有一些观察:

  1. 我们需要存储数十亿条记录。
  2. 我们存储的每个元数据对象都很小(小于 1 K B 1KB 1KB)。
  3. 我们存储的每个粘贴对象大小适中(可以达到几MB)。
  4. 记录之间没有关系,除非我们要存储哪个用户创建了哪个粘贴内容。
  5. 我们的服务主要是读取操作。

数据库架构

我们需要两个表,一个用于存储粘贴内容的信息,另一个用于存储用户的数据。

Pastebin设计之旅:从零设计网络文本存储系统

这里,URlHash是TinyURL的URL等效项,ContentKey是指向一个外部对象的引用,该对象存储粘贴内容的内容;我们将在本章后面讨论粘贴内容的外部存储。

7、顶层设计

在顶层设计上,我们需要一个应用层来处理所有的读取和写入请求。应用层将与存储层进行通信,以存储和检索数据。我们可以将存储层划分为两部分,一部分数据库存储与每个粘贴内容、用户等相关的元数据,另一部分将粘贴内容存储在某些对象存储中(如阿里云OSS)。这种数据的划分也允许我们单独进行扩展。

Pastebin设计之旅:从零设计网络文本存储系统

8、组件设计

A. 应用层

我们的应用层将处理所有的进出请求。应用服务器将与后端数据存储组件进行通信以服务这些请求。

如何处理写入请求?在收到写入请求后,我们的应用服务器将生成一个六位随机字符串,这将作为粘贴的键(如果用户没有提供自定义键)。然后,应用服务器将粘贴的内容和生成的键存储在数据库中。成功插入后,服务器可以将键返回给用户。这里可能存在的一个问题是由于键重复而导致插入失败。由于我们是生成一个随机键,所以新生成的键可能与现有的键相匹配。在这种情况下,我们应该重新生成一个新的键并再试一次。我们应该一直重试,直到我们不再因为重复键看到失败。如果用户提供的自定义键已经在我们的数据库中存在,我们应该向用户返回一个错误。

上述问题的另一种解决方案可能是运行一个独立的键生成服务(KGS),它提前生成随机的六位字符串,并将它们存储在数据库中(我们称之为key-DB)。每当我们想要存储一个新的粘贴,我们只需要取一个已经生成的键并使用它。这种方法将使事情变得非常简单和快速,因为我们不会担心重复或碰撞。KGS将确保所有插入key-DB的键都是唯一的。KGS可以使用两个表来存储键,一个用于尚未使用的键,一个用于所有已使用的键。一旦KGS向应用服务器提供了一些键,它可以将这些移动到已使用的键表中。KGS可以始终在内存中保持一些键,以便每当服务器需要它们时,它可以快速提供。一旦KGS在内存中加载了一些键,它就可以将它们移动到已使用的键表中;这样我们就可以确保每个服务器获取到的键都是唯一的。如果KGS在使用所有加载到内存中的键之前死掉,我们将浪费这些键。我们可以忽略这些键,因为我们有大量的键。

KGS会出现单点故障吗?会的。为了解决这个问题,我们可以有一个备用的KGS副本,每当主服务器死掉时,它可以接管来生成和提供键。

每个应用服务器可以从**key-DB**中缓存一些键吗?是的,这肯定可以加快速度。虽然在这种情况下,如果应用服务器在消费所有键之前死掉,我们将最终丢失那些键。这可能是可以接受的,因为我们有 68 B 68B 68B个唯一的六位字母键,这比我们需要的要多得多。

如何处理粘贴读取请求?在收到读取粘贴请求后,应用服务层联系数据存储。数据存储搜索键,如果找到了,就返回粘贴的内容。否则,返回一个错误码。

B. 数据存储层

我们可以将我们的数据存储层分为两部分:

  1. 元数据数据库:我们可以使用像MySQL这样的关系数据库,或者像DynamoCassandra这样的分布式Key-Value存储。
  2. 对象存储:我们可以将我们的内容存储在像阿里云OSS这样的对象存储中。每当我们感觉到我们的内容存储容量已经满了,我们可以通过平台直接扩容。

Pastebin设计之旅:从零设计网络文本存储系统

9、数据分区和复制

为了扩展我们的数据库,我们需要对其进行分区,以便它能存储数十亿个URL的信息。因此,我们需要设计一个分区方案,将我们的数据划分并存储到不同的数据库中。

A. 基于范围的分区:我们可以根据哈希键的第一个字母在不同的分区中存储URL。因此,我们将所有以字母“A”(和“a”)开头的URL哈希键存储在一个分区中,将以字母“B”开头的URL存储在另一个分区中,以此类推。这种方法被称为基于范围的分区。我们甚至可以将某些出现频率较低的字母组合到一个数据库分区中。因此,我们应开发一个静态分区方案,始终以可预测的方式存储/查找URL

这种方法的主要问题是可能导致数据库服务器不平衡。例如,我们决定将所有以字母“E”开头的URL放入一个数据库分区,但后来我们发现以字母“E”开头的URL过多。

B. 基于哈希的分区:在这种方案中,我们对存储的对象进行哈希。然后,我们根据哈希值计算使用哪个分区。在我们的情况下,我们可以获取key或短链接的哈希值,以确定我们存储数据对象的分区。

我们的哈希函数将随机地将URL分配到不同的分区(例如,我们的哈希函数可以始终将任何key映射到[1…256]之间的一个数字)。这个数字将表示我们存储对象的分区。

这种方法仍然可能导致分区负载过大,这可以通过使用’一致性哈希’来解决。

10、缓存

我们可以缓存频繁访问的URL。我们可以使用任何现成的解决方案,比如Memcached,它可以存储完整的URL及其对应的哈希值。因此,应用服务器在访问后端存储之前,可以快速检查缓存是否有所需的URL

我们应该有多少缓存内存?我们可以从日流量的20%开始,根据客户的使用模式,我们可以调整需要多少缓存服务器。如上所估计,我们需要170GB的内存来缓存日流量的20%。目前的一些服务器可以拥有256GB的内存,我们可以轻松将所有缓存放入一台机器。或者,我们可以使用几台小一点的服务器来存储所有这些热门URL

哪种缓存驱逐策略最适合我们的需求?当缓存满了,我们想用一个新的/更热门的URL替换一个链接,我们应该如何选择?最近最少使用(LRU)可能是我们系统的一个合理策略。根据这个策略,我们首先丢弃最近最少使用的URL。我们可以使用Linked Hash Map或类似的数据结构来存储我们的URL和哈希值,这也会记录最近访问过的URL

为了进一步提高效率,我们可以复制我们的缓存服务器来分配它们之间的负载。

每个缓存副本如何更新?每当有一个缓存未命中,我们的服务器会访问后端数据库。当这种情况发生,我们可以更新缓存,并将新的条目传递给所有的缓存副本。每个副本都可以通过添加新的条目来更新其缓存。如果副本已经有了该条目,它可以简单地忽略它。

Pastebin设计之旅:从零设计网络文本存储系统

11、负载均衡(LB)

我们可以在系统中的三个位置添加负载均衡层:

  • 客户端与应用服务器之间
  • 应用服务器与数据库服务器之间
  • 应用服务器与缓存服务器之间

最初,我们可以使用一个简单的轮询方法,将进入的请求均等地分配到后端服务器。这种负载均衡方法简单易行,不会引入任何额外的开销。这种方法的另一个优点是,如果一个服务器死机,负载均衡器会将其从轮询中移除,停止向其发送任何流量。

轮询负载均衡的一个问题是,我们没有考虑到服务器的负载。如果一个服务器过载或运行缓慢,负载均衡器不会停止向该服务器发送新的请求。为了处理这个问题,我们可以放置一个更优的负载均衡解决方案,它定期查询后端服务器的负载,并根据负载情况调整流量。

12、清除或数据库清理

key条目是否应永久存在,还是应该被清除?如果达到用户设定的过期时间,链接应该怎么处理?

如果我们选择持续寻找过期链接并将其删除,这将对我们的数据库产生很大压力。相反,我们可以慢慢地删除过期的链接,进行懒人清理。我们的服务将确保只删除过期的链接,尽管有些过期链接可能会存在更长时间,但永远不会被返回给用户。

  • 每当用户试图访问一个已过期的链接,我们可以删除该链接并向用户返回错误。
  • 我们可以设置一个单独的清理服务,定期从我们的存储和缓存中删除过期的链接。这个服务需要非常轻量,只在预计用户流量较低的时候运行。
  • 我们可以为每个链接设定一个默认的过期时间(例如两年)。
  • 删除过期链接后,我们可以将该Key重新放回Key-DB,以供重复使用。
  • 我们是否应删除一段时间(比如说六个月)内没有被访问过的链接?这可能有点不合适。由于存储成本越来越低,我们可以决定永久保存链接。

Pastebin设计之旅:从零设计网络文本存储系统

13、数据跟踪

我们如何统计短链接被使用的次数、用户的位置等信息?我们如何储存这些统计信息?如果它是数据库中的一部分,每次查看都需要更新,那么当一个流行的短链接被大量并发请求瞬间涌入时,会发生什么?

一些值得追踪的统计数据:访客的国家、访问的日期和时间、引导点击的网页、访问页面的浏览器或平台。

14、安全和权限

用户能否创建私有URL或者允许特定的用户组访问某个URL

我们可以在数据库中每个URL的条目里存储访问权限级别(公开/私有)。我们也可以创建一个单独的表来存储有权访问特定URL的用户的UserID。如果一个用户没有权限但试图访问一个URL,我们可以返回一个错误(HTTP 401)。考虑到我们的数据储存在一个类似CassandraNoSQL宽列数据库中,储存权限的表的key将是‘哈希值’(或KGS生成的key)。列将储存有权查看URL的用户的UserID文章来源地址https://www.toymoban.com/news/detail-510179.html

到了这里,关于Pastebin设计之旅:从零设计网络文本存储系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Django爬虫项目网络表情包爬虫展示系统设计与实现(Pycharm+Python+Mysql)

     博主介绍 :黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,学习后应对毕业设计答辩。 项目配有对应开发文档、

    2024年03月15日
    浏览(42)
  • 从零开始构建区块链:我的区块链开发之旅

    1.区块链技术的兴起和重要性 区块链技术,作为数字化时代的一项颠覆性创新,已经成为当今世界最令人瞩目的技术之一。自比特币的问世以来,区块链技术已经从仅仅支持加密货币发展成为一种具有广泛应用前景的分布式账本技术。其核心优势在于提供了一种安全、透明、

    2024年02月02日
    浏览(40)
  • 文本语音互相转换系统设计

    title: 文本语音互相转换系统设计 date: 2024/4/24 21:26:15 updated: 2024/4/24 21:26:15 tags: 需求分析 模块化设计 性能优化 系统安全 智能化 跨平台 区块链 第一章:背景与意义 文本语音互相转换系统的定义与作用 文本语音互相转换系统是一种能够将文本信息转换为语音,或将语音信息转

    2024年04月24日
    浏览(41)
  • 300人工厂网络规范部署从零规划选型设计到实战全过程

    公司新建了一个2000多平方的工厂,约300多名员工,整个厂房的生产和办公区域需要有线和无线网络覆盖,满足有线和无线 办公和工厂设备连接, 以及各个位置监控部署、门禁使用。 1. 宽带套餐选型     前期根据工厂CAD平面布局图,规划有线点位、无线点位、门禁点位、监

    2024年02月02日
    浏览(52)
  • Python 实现经典游戏“贪吃蛇”:从零开始的趣味编程之旅

    在计算机科学和编程教育中,通过实现小游戏是学习和掌握一门编程语言的重要实践方式。今天,我们将一起探索如何使用Python来打造一款经典的、风靡全球的游戏——贪吃蛇。这个项目不仅涵盖了Python的基础语法、面向对象编程思想,还会涉及pygame库的使用以及游戏循环、

    2024年02月21日
    浏览(48)
  • 系统设计:从零用户扩展到百万用户

    设计一个支持百万用户的系统是具有挑战性的,这是一段需要不断改进和不断提升的旅程。在本章中,我们将构建一个支持单个用户的系统,并逐渐扩展以服务于数百万用户。阅读本章后,您将掌握一些技巧,帮助您解决系统设计面试问题。 AI不会取代你,使用AI的人会。欢迎

    2024年02月06日
    浏览(39)
  • 从零开始的网络安全--Windows系统安全(1)

    1、用户账户概述 用户账户用来记录用户的用户名和口令、隶属的组等信息 每个用户账户包含唯一的登录名和对应的密码 不同的用户身份拥有不同的权限 操作系统根据SID识别不同用户 每个用户拥有唯一安全标识符(SID) 用户权限通过用户的SID来记录 查看命令为:whoami /us

    2024年01月22日
    浏览(47)
  • 系统设计(架构师)指南1从零扩展到百万用户

    设计支持数百万用户的系统是一项挑战,是需要不断完善和无止境改进的过程。在本章中,我们将构建一个支持单个用户的系统,并逐步将其扩展到为数百万用户提供服务。 下图展示了单服务器设置的示意图,其中所有内容都运行在一台服务器上:网络应用程序、数据库、缓

    2024年02月10日
    浏览(43)
  • 从零到Kafka:万字带你体验Spring Boot整合消息驱动的奇妙之旅

    主页传送门:📀 传送 Spring boot : | 基于Spring的开源框架,用于简化新Spring应用的初始搭建以及开发过程 特性: | 快速开发、轻量级、无代码生成和独立运行等特性 优势: | 简化配置,提供自动配置,减少开发时间 应用场景: | 适用于微服务架构、云原生应用等场景 环境

    2024年02月05日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包