像TinyUrl和Bit.ly这样的短链接服务是怎么运作的?
2024/10/13 3:03:17
本文主要是介绍像TinyUrl和Bit.ly这样的短链接服务是怎么运作的?,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
我们经常在线上分享信息。无论是文章、视频还是产品,网址(URLs)是访问这些内容的入口。然而,长网址分享起来可能会很麻烦,尤其是在像社交媒体或消息应用这样的平台上,这些平台有字数限制。这时像 bit.ly 和 TinyURL 这样的网址就派上用场了。
它们有助于将长链接缩短并使其更易读。这些缩短的链接不仅看起来更简洁,还使跨平台分享内容变得轻松自如。
现在你知道了这个秘密,想象全球每天有数百万人在缩短网址链接。这给底层系统带来了巨大的压力。而这正是系统架构设计大显身手的地方。
从这个关于系统设计的系列开始,我们的目标是剖析每个系统所涉及的功能性、架构、挑战、扩展性、系统API、性能和资源估算。我们将提供必要的洞察力,帮助你在实际情况中解决类似的问题。就像编程不仅仅是写代码一样,设计也意味着培养直觉并形成有条理的思考方式。因为没有清晰的设计思路,你无法写出好代码。
如果这还不行,请读到最后,文章末尾有一个特别惊喜,可能让你的系统设计技能大幅提升!
通过这一系列,我们希望提高你的设计感,并帮助你成为一个技术娴熟、有好奇心的工程师,能构建大规模系统。
如果你对这些概念完全不了解,或者这是你第一次听说它们,并且想要了解系统设计的基本模块的基础,我们为你准备好了相关内容。
我们正在做一个关于系统设计101入门系列的歌单——这是链接
如果你对系统设计不太了解,这里有一些很酷的东西你可以了解下。
- 序列生成器
- 编码类型:Base 58,Base 64
- 全球服务器负载平衡
- 估算资源时的手写数学计算
如果你完全不了解这些概念,或者第一次听说这些概念,并希望首先掌握系统设计的基础知识,我们帮到你。在继续看下面的文章之前,你可以先看看下面的视频。
我们准备聊一聊系统设计方面的内容。
我们把它分成了7个模块
1. 功能性和非功能性需求
2. 资源估算 — 服务器、带宽、存储
3. 构建块的深入探讨为什么和怎么做
4. 系统API接口
5. 组件及其工作流程图
6. 编码方案及相关计算
7. 非功能性需求的映射
- 容易记住或输入:得益于其增强的可访问性和不可断性,它们使不同设备上的链接使用更优化。
- 它们看起来很专业,吸引人,并促进了更高的共享可能性。
- 它们在用户的设备上占用较小的存储空间。
该系统的实际功能将包括以下几点。不了解需求的话,真的很难开始设计,是吧?
- 短网址生成:我们的服务应当能够为给定的URL生成一个唯一的简称。
- 重定向:给定一个短链接,我们的系统应当能够重定向到原始网址。
- 自定义短链接:用户应该能够使用我们的系统为其URL创建自定义短链接。
- 删除:用户应该能够删除自己创建的短链接。
这些标准说明了系统应该如何表现,而不是它应该完成的任务。
- 可用性 :我们的系统应该是高度可用,因为即使是一小部分的系统停机也会导致URL重定向失败。由于我们的系统域名存在于URL中,我们没有系统停机的回旋余地,因此我们的设计必须具备容错机制。
- 可扩展性 :随着需求的增加,我们的系统应该能够横向扩展。
- 可读性 :系统生成的短链接应该是易于阅读、区分度高和输入的。
- 延迟 :系统应该低延迟运行,以给用户提供流畅的体验。
- 不可预测性 :从安全角度来看,系统生成的短链接应该具有高度的不可预测性。这确保了下一个短URL不会按序生成,从而防止有人猜测系统生成的所有短链接。
在这部分,我们将通过一些数学计算来计算我们需要多少资源来支持我们的系统。这很重要,因为当我们在建造或开发某个系统时,我们需要预估它可以增长到什么规模,并提前规划存储、带宽、服务器等资源需求,等等。
- 我们假设 缩址:重定向 请求比例为 1:100
- 每月有 2亿 新的 URL 缩址请求。
- 每个 URL 缩短条目需要占用 500 字节 的数据库空间。
- 每个条目默认的过期时间为 五年,除非被明确删除。
- 每日活跃用户(DAU)约为 1亿。
我们来拆解一下:
- 缩短网址与重定向请求比为1:100:这意味着每次有网址缩短请求时,就会产生100次对该缩短网址的重定向。
- 每月有2亿次新的网址缩短请求:这表示每月用户想要缩短的网址数量。也就是说,在一个月内,有2亿个独特的网址需要被缩短。
- 每个缩短网址条目需要占用500字节的数据库存储空间:每个被缩短并存储在数据库中的网址需占用500字节的存储空间。这包括了所有用来重定向到原始网址的信息。
- 每个条目最多有五年的失效时间,除非被明确删除:这意味着数据库中的每个网址条目从创建之日起最多可以保持五年活跃状态。除非在此之前被删除,它将自动过期并从数据库中移除。
- 每日活跃用户(DAU)为1亿:这表示每天使用该服务的用户数量。这些用户每天都在积极创建缩短网址、点击缩短链接,或同时进行。
存储估算:
由于条目保存期限为5年,且每月大约有2亿条目,因此总条目数将约为120亿。
因为每个条目是500字节,也就是说,总存储量估计为6 TB。
我们正在估算每秒会有多少个URL(统一资源定位符)。
这以后会帮助我们算带宽。
根据上述估计,我们预计每月会有20亿次重定向请求量,对应200万次网址缩短请求量。
我们每月处理2亿个URL缩短和200亿次重定向。
我们可以基于这个基准来计算我们系统的每秒查询数(QPS)。按照平均每月的天数,一个月大约有2,592,000秒。
采用1:100的比例进行重定向,每秒的URL重定向次数:
带宽(Bandwidth)= 数据流量 × 平均响应大小(Average Response Size)
- 流量(请求量)是指单位时间内请求数(例如,每秒的请求数量)。
- 平均响应的大小是指以字节为单位的平均大小。
请求缩短:我们预计每秒会有77个新网址。
这相当于每秒总的输入数据量将是这样的:大约308 Kbps。
重定向请求:预计的重定向速率为每秒7.7K URL,总数据输出量为30.8 M bps (比特每秒)。
入站带宽=308 Kbps
出站带宽 = 30.8 Mbps
在计算这个系统所需的大概服务器数量之前,让我们考虑一个小例子:
假设:
- 每日活跃用户(DAU)有5亿(M)。
- 每个用户平均每天发出20次请求。
- 要知道,单个服务器每秒可以处理8,000个请求(RPS)。
当我们说15个服务器可以满足5亿用户的需求时,从数学的角度来看,这似乎不太对。大型服务通常会使用更多的服务器,因为仅仅计算每秒的请求数量远远不能反映出服务器的全部需求。
此外,这种计算假设每个请求都是由一个单独的服务器处理的,但实际上,请求可能需要经过多种类型的服务器,包括网页服务器、应用服务器和存储服务器。
因此,来计算所需的服务器数目,我们将考虑以下两个因素:
- 每日活跃用户数(DAU,Daily Active Users)
- 服务器每日可处理的最大用户数
一个更实际的数字是12,500台服务器。
我们需要估算一下内存需求,因为在我们想缓存一些频繁访问的重定向请求时就会用到内存。假设20%的重定向请求产生了80%的流量,且这些请求中存在80-20的分布。
由于我们只会缓存这些每日重定向请求的20%,所需的总内存大约为66GB。
那么,66GB的缓存容量就挺好的。
到了宣布的时候了。
如果你喜欢这些内容,你一定会超级喜欢我在YouTube频道上的内容。
我们为粉丝提供一系列专属福利,包括虚拟视频合作项目、会员专属投票、专为会员提供的高质量内容等,更多精彩内容即将推出,敬请期待。
在本文的背景下,我们的独家视频将引导您了解系统设计的所有重要方面,深入探讨各个组件,提供额外的数学概念理解,分享实用技巧,并提供一些实用策略,帮助您提升系统设计技能。
我是谁啊?
在过去7年里,我领导了涉及AWS、Java、Spring Boot、Kafka、ELK栈、Splunk、Apache Mesos等项目的实施,通过优化系统,提升了成本效益,实现了高达30%的成本节约,通过性能调优,延迟降低了50%,同时使系统能够处理更多的交易。
所以,我完全可以肯定你可以依赖我的专业知识。
除此之外,我们还将提供专门针对Java线程和并发常见面试问题的视频,详细的Spring Boot项目计划,以及许多项目灵感。所有这些特别内容都是专为你准备的哦!
支持我们频道的同时,加入我们日益壮大的社区,享受独家内容。
要立即加入我们,成为有价值的一员,请点击链接。
完成估算之后,我们就能识别出设计中的关键组件。
- 数据库:存储长URL到短URL的映射。
- 序列器:生成短URL的基础。
- 负载均衡器:确保请求在各个层级上均匀分布。
- 缓存:存储最频繁的短URL请求。
- 速率限制器:防止系统被恶意利用。
- 服务器:处理服务请求,导航并执行应用程序逻辑。
- Base-58编码器:转换成易读且实用的字母数字形式。
为了展示我们服务的功能性,我们可以使用 REST APIs 来实现以下功能特性:
- 缩短URL
- 跳转短URL
- 删除短URL
我们可以按照以下定义创建短的新的网址。
插入成功后返回缩短的URL给用户。否则,系统会返回相应的错误代码给用户。
要将短网址重定向,该 REST API 的定义将是:
成功的重定向后将用户带到与之相关的该原始 URL。
同样,要删除短网址,REST API 的定义将如下所示。
删除成功后,系统会显示消息“URL已成功移除”
我们来看看我们需要存的是什么数据
用户数据:
- 用户ID : 用于唯一标识用户的特殊ID或API密钥。
- 用户名 : 用户名。
- 用户邮箱 : 用户邮箱。
- 用户注册日期 : 用户注册日期。
短链接:
-
短链接: 通常只有7个字符的唯一短链接。
-
原始长链接: 原始的长链接。
- UserID : 生成短链接的用户唯一ID或API密钥。
- 数据库:对于诸如网址缩短这样的服务,所需的数据量非常小。然而,存储需求必须能够水平扩展。我们需要存储的数据类型包括:
- 用户信息。
- URL转换:长URL 转换成 短URL。
为什么需要水平扩展?
对于像网址缩短这样的服务来说,水平扩展非常重要,因为它能够处理不断增长的流量和数据,而不会让系统超负荷。
NoSQL 数据库会是一个很好的选择,因为我们预计系统中会有大量的 读取 请求。此外,除了与创建 URL 的用户相关的详情外,存储的记录是独立的,它们之间没有其他联系。
MongoDB 挺不错的一个选择,因为:
- 它可以使用副本进行重读。
- 它擅长处理同时进行的写操作,没有任何问题。
一个 NoSQL 数据库非常适合我们的系统,因为它可以处理大量的读取而不变慢。它可以处理不同类型的数据,且扩容容易。此外,即使很多人同时访问,它也能快速找到我们需要的信息。
2.短链接生成器 :
我们的短链接生成器分为两部分:
- 一个用于创建唯一标识符的序列器
- 一个Base-58编码器,用于使短链接更易读。
序列生成器:
在 URL 缩短服务中,生成独一无二的缩短 URL 的唯一 ID 至关重要。这通常通过递增计数器或运用分布式算法跨多个服务器生成 ID 并避免冲突来实现。这确保了即使在高并发和快速的 URL 缩短请求下,每个缩短的 URL 都会获得一个唯一的 ID,避免冲突并确保服务的完整性。
Base-58 编码:
生成唯一的ID虽然重要,但创建易于阅读和分享的短URL对于用户体验来说同样重要。这时,Base-58编码就派上用场了。Base-58编码类似于Base-64编码,但是去除了0(零)、O(大写字母O)、I(大写字母i)和l(小写字母L)这样的字符,这样可以避免混淆并提高可读性。
3. 负载平衡
为了保证高可用性,我们将会用到。
- 全局服务器负载平衡(GSLB): 将请求分配到全球各地的服务器,特别是在发生现场故障时,确保高效的流量管理。
- 本地负载平衡。
为什么需要两者?
全球服务器负载均衡对于多个地理位置分散的数据中心或区域之间的传入流量分配至关重要。随着全球在线服务的普及以及用户对低延迟体验需求的增加,全球负载均衡对于在不同地区保持一致性能至关重要。它使公司能够有效地为全球各地的客户提供服务,并通过将流量从出现问题或中断的地区转移出去确保服务的高可用性。
局部负载均衡关注在一个数据中心或网络内部分配流量,以优化资源利用率、加快响应时间并避免单个服务器过载。
4. 缓存:Memcached 可以为我们的 读密集型 应用提供理想的缓存解决方案。在每个数据中心可以实现一个缓存层来处理来自附近的请求。我们之前也讨论过缓存存储的需求。
5. 速率限制: 每个用户将拥有一个唯一的密钥:api_dev_key
,该密钥将限制你在一段特定的时间内可以缩短和重定向链接的任务的数量。
我们来探索系统每个部分是如何一起工作来实现它们的功能。
- 短链接生成:当用户请求一个短链接时,应用服务器将请求转发给短链接生成器(SUG)。一旦短链接生成成功,会将链接发送给用户,并将
url_key
存储在数据库中以便将来使用。 - 重定向请求:当用户请求重定向时,应用服务器会在缓存系统和数据库中查找所需的记录信息。如果找到,用户将被重定向到相应的原始链接;否则,会显示一个错误消息。
- 删除:可以通过向应用服务器请求来删除一条记录,应用服务器会检查缓存系统和数据库中的所需记录信息。如果找到,
url_key
及其记录将被删除;否则,会显示一个错误消息。 - 自定义短链接:系统会检查请求的短链接的有效性,确保它符合条件(最大长度为11个字母数字字符)。如果符合条件,系统会在数据库中检查其可用性。如果可用,用户会收到一条成功生成的短链接消息;否则,会显示一个错误消息。
下面是一张图解,如图所示:
编码在网址缩短过程中将原始数据,如字母和符号,转换为一种编码格式,这种编码格式更适合在互联网上发送。这种转换过程保证了创建的短网址对于URL来说是安全的,并且在使用或分享时不会出现问题。
有很多不同的编码方式:
- Base 64 编码: 采用包含64个字符的字符集(A-Z,a-z,0-9,+,/)来表示二进制数据。
- Base 62 编码: 与Base 64类似,但不包括不安全的URL字符,例如 + 和 /。它使用包含62个字符的字符集(A-Z,a-z,0-9)。
- Base 58 编码: 是Base 62的一种变体,进一步排除了与0(零)、大写的O、大写的I和小写的L相似的字符以提高可读性。
我们系统采用Base58编码以提高可读性,并避免因视觉相似字符引起的混淆。
Base58 编码 (来源链接)
我们来看看如何将一个数从58进制转换为10进制,以及反过来怎么做。
将Base 58转Base 10:
十进制转五十八进制:
我们快速算一下最佳短网址长度。
长度为5的URL会生成58⁵ = 约6亿5600万个URL 长度为6的URL会生成58⁶ = 约38亿个URL
我们的系统生成12亿个URL(存储利用率考虑),使用6个base58字符可以生成大约38亿个URL。因此,每个生成的短链接将包含6个字符。
短链接的序列生成从哪里开始?
让我们来分解一下。当你给我们一个长长的网址需要缩短时,我们会用到一个叫SUG(短网址生成器)的工具。它由两部分构成:序列生成器和base 58编码器。
现在,当我们得到一个长链接时,我们首先通过序列器生成一串数字。然后将这些数字转换成base 58编码,这样就得到了一个由6个字符组成的短链接。但是有个问题:我们从哪里开始计数,以便正好得到6个字符的链接?这正是我们需要解决的问题。
通过逆向计算发现,要达到至少6个字符的base-58,相应的base-10数值大约是10亿。
这个数是:十进制数:1000000000
1000000000 % 58 = 18 17241379 % 58 = 9 297265 % 58 = 15 5125 % 58 = 21 88 % 58 = 30 1 % 58 = 1 以58为底的等效表示: [1][30][21][15][9][18] : 2XNGAK
所以,长度为6的 base 58 序列对应的最小 base 10 数字是 10亿(即 1,000,000,000)。短链接生成器将从 10亿 开始为任何用户生成短链接。
所以我们现在能理解,我们的设计能满足功能需求了。
那我们该怎么满足这些非功能性的需求呢?
让我们聊聊并做个总结。
- 构建块将具有内置复制;以确保系统的可用性和容错性。
- 全球负载均衡(GSLB) 用于处理系统的流量,以分发请求。
- 速率限制器 用于限制每个用户的资源使用量;并防止分布式拒绝服务(DDoS)攻击。
- 使用水平分片数据库。
- MongoDB — 一种非关系型数据库。
- 介绍base-58编码器,用于生成短URL。
- 移除非字母和数字字符。
- 移除容易混淆的字符。
MongoDB,在读取操作方面具有低延迟、高吞吐量
通过从分配给每个服务器的ID池中随机选择一个未使用过的唯一ID,这种方法不同于按顺序分配ID,从而降低了预测后续短网址的可能性。
此外,使用如SHA-256这样的加密哈希函数对原始URL进行哈希,然后将该哈希值编码成一个较短的表示会更佳。
这篇文章到此结束。
谢谢阅读。
如果你喜欢这篇文章的话,请多点几下 👏。
这让我有动力去创作更多类似的内容。请分享给你觉得这篇文章可能帮到的人。
联系我 — 瓦尔莎·达斯 |LinkedIn
如果你对此感到安心,我在软件工程、职业发展、核心Java、系统设计或面试准备方面提供个性化指导,让我们在这里连接 here。
请放心,我全心全意投入其中。我真心热爱解决复杂问题,提供量身定制的解决方案,并与来自各种背景的人互动。
订阅我的YouTube频道 — Code With Ease — By Varsha,在那里,我们聊聊Java、数据结构和算法等等话题。
点击这里订阅我的Medium账号,每次我发布新文章时,你都会收到通知。
学习快乐,一起成长。
这篇关于像TinyUrl和Bit.ly这样的短链接服务是怎么运作的?的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15快速提升职场效率:从整理任务清单开始
- 2024-11-15低代码开发学习:新手入门指南
- 2024-11-15数字能量的职场释放:实物量法诠释效率的多维度
- 2024-11-15Postman学习:新手入门全面指南
- 2024-11-15低代码开发入门:初学者必看指南
- 2024-11-15低代码入门:新手必读指南
- 2024-11-15低代码应用入门:新手必读教程
- 2024-11-15Postman入门:新手必备教程
- 2024-11-15Postman教程:新手快速上手指南
- 2024-11-14企业协同软件:现代化管理的新选择