1*xOHz3T_iSShM2rRIT2bljA.png
这是一个系统设计问题,需要从头设计一个类似于TinyURL或Bitly的URL短链接工具。我们涵盖从设计要求、架构和组件设计到高性能扩展和安全最佳实践的所有内容。
定义范围:功能性和非功能性需求
首先,您需要定义系统的功能和非功能需求。
有两个功能要求。
1. 给定一个长URL,您需要创建一个短URL。 2. 给定一个短URL,您需要将用户重定向到一个长URL。
1*jAM1f_jvXWxmPVRjiweF0g.png
服务的非功能性需求优先考虑低延迟(快速响应)和高可用性(始终开启)。
1*jNP-rIMTYsFG6wq8Hu4cnA.png
明确业务问题
为了持续了解系统的规模,您可能需要提出以下问题:
• 使用情况:估计每秒需要创建的URL 数量(假设1000)。字符:可以使用数字、字母(字母数字字符)和其他符号吗? (假设字母数字字符)。 •唯一性:即使多个用户提交相同的长URL,每次生成的短URL是否唯一?(此设计假设唯一性。)
估算:数据计算
您需要使用此信息来计算缩短的URL 的长度。当然,您希望使其尽可能短,但您还需要考虑每年创建的URL 数量。
1*KSIMBkGNZ7RzwWQRZ22uNA.png
首先,估计随着时间的推移您将需要多少个唯一URL。一般方法是规划至少几年的运营。为了简化计算,我们假设10 年的数据。
1年的秒数:1分60秒1小时60分钟10年的URL总数:100031536万=3153.6亿个唯一URL
这意味着数据库每秒必须处理1000 次写入,每年产生1000606024365=315 亿个URL。假设读取次数通常是写入次数的10 倍,这意味着每秒读取次数超过10×1000=10000 次。
现在您需要计算出有多少字符可以为未来10 年的数量提供足够的独特缩短URL。考虑到字符集大小为62,URL标识符的长度可以计算如下:
• 621=62 个唯一URL(1 个字符) • 62=3844 个唯一URL(2 个字符) • …等等。
1*v92u6EyCjrSdC2G9dfdkzQ.png
继续计算,我们发现62(大约3.5 万亿)是第一个大于估计的3150 亿个所需URL 的值。
因此,缩短的URL 应至少为7 个字符,以支持未来10 年的预期增长。
高层次架构
我们的系统有以下主要组成部分:
用户:用户应该提交长URL以生成短URL,或者提交短URL并被重定向到长URL。
负载均衡器:所有这些请求都经过负载均衡器。负载均衡器在多个Web 服务器实例之间分配流量,以确保高可用性和负载均衡。
Web 服务器:这些服务器副本处理传入的HTTP 请求。
URL短链接服务:您还需要一个URL短链接服务,其中包括生成短URL、存储URL映射以及检索原始URL进行重定向的核心逻辑。
数据库:存储短URL和长URL之间的连接。在设计数据库之前,您应该考虑缩短的URL 的潜在存储要求。
每个URL 都包含一个唯一标识符(大约7 个字节)、一个长URL(最多100 个字节)和用户元数据(估计为500 个字节)。这意味着每个URL 最多需要1000 个字节。根据预期量,这相当于大约315 TB 的数据。
1*mMbzPSeZtYyVyjcmi2rqVw.png
在继续之前,让我们考虑一下单个Web 服务器的API 设计。
API设计
让我们为我们的服务定义基本的API 操作。根据您的功能要求,您将使用REST API 并需要两个端点。
1. 创建缩短的URL (POST**/urls**)
输入:带有长URL 的JSON 负载{\”longUrl\” : \”[https://example.com/very-long-url](https://example.com/very-long-url)\’}
输出:包含缩短的URL {\”shortUrl\” : \”[https://tiny.url/3ad32p9](https://tiny.url/3ad32p9)\’} 和201 Created 状态代码的JSON 负载。
如果请求无效或格式错误,则返回400 错误请求响应;如果系统上已存在请求的URL,则返回409 冲突。
2. 重定向到长URL (GET**/urls/{shortUrlId}**)。
输入:shortUrlId 路径参数
输出:响应301 永久移动。响应正文包含新创建的缩短URL,格式为JSON{ \’shortUrl\’: \’https://tiny.url/3ad32p9\’ }。
1*wNufw9wtsv-tV0G20eDuAA.png
301 状态代码表示您的浏览器正在缓存信息。这意味着下次用户输入短URL 时,浏览器将自动重定向到长URL,而无需再次联系服务器。
但是,如果您想跟踪每个请求的分析并确保它通过您的系统,则可以使用302 状态代码。
数据库:存储短URL
下一部分是数据库层。该层存储短URL 和长URL 之间的映射。必须针对快速读写操作进行优化。
模式可以很简单。对短URL ID 和长URL 使用主键,并可能创建元数据字段。
{
\’shortUrlId\’: \’3ad32p9\’,
\’longUrl\’: \’https://example.com/very-long-url\’,
\’创建日期\’: \’2024-03-08T12:00:00Z\’,
\’用户ID\’: \’用户123\’,
“点击”: 1023,
\’元数据\’: {
\’title\’: \’网页示例\’,
\’tag\’: [\’示例\’, \’网络\’, \’URL 缩短器\’],
\’到期日\’: \’2025-03-08T12:00:00Z\’
},
\’isActive\’: true
}
这里要考虑的主要问题是从数据库读取的次数。通常,如果每秒写入1000 次,则每秒至少可以读取10-100000 次。
在这种情况下,您应该使用支持快速读写的高性能数据库。这意味着您需要使用NoSQL 数据库(诸如MongoDB 之类的文档存储、诸如Cassandra 之类的宽列存储或诸如DynamoDB 之类的键/值存储)。这是因为NoSQL 数据库是专门为处理大规模扩展而设计的。
1*qDll9-tFr2I2OxhWO3wSHg.png
它不符合ACID,但我不关心这一点,因为我不做大量JOIN 或复杂查询,而且我不需要ACID 规则或原子事务。
URL短链接服务
系统的核心部分之一是URL短链接服务。即使不同的长URL 指向相同的短URL,此服务也会生成短URL,而不会引起冲突。
有多种方法可以实现此服务。这里是其中的一些:
•哈希:生成长URL 的哈希并使用其中的一部分作为标识符。但是,哈希可能会导致冲突。 • 自增ID:使用数据库的自增ID 并将其编码为短字符串。这确保了唯一性,但也可以预测。 • 自定义算法:设计自定义算法,将字符组合起来生成唯一的ID,以确保唯一性和不可预测性。
例如,可以生成一个非常简单的方法——来避免冲突。
将所有可能的7 字符密钥作为密钥存储在数据库中。键是生成的URL,值是布尔值。如果为true 则表示该URL 已在使用中,如果为false 则表示该URL 可用。映射。
因此,每当用户请求生成密钥时,您都可以在此数据库中找到当前未使用的URL,并将其映射到请求正文中的长URL。
在这种情况下,您愿意使用SQL 数据库还是NoSQL 数据库?让我们考虑一个场景。两个用户请求缩短一个长URL,并且两个用户都映射到该数据库中的相同键。
1*b0c8CnuESVxCE2-Ux7QPqA.png
在这种情况下,URL 将被映射到其中一个请求,而另一个请求将被破坏。所以我们使用具有ACID 属性的SQL。您可以在此处为每个会话创建一个事务以单独执行这些步骤。这样的话,就不会出现这个问题。
高可用性和低延迟
当前系统显然无法处理每秒1000 个URL 的流量。
1*eN5OY1eSi9SnGHqgVgF9bg.png
缓存
为了提高可扩展性,您首先需要一个缓存层(例如Redis)来缓存流行的URL,以便在内存中快速检索。
某些URL 的访问可能比其他URL 更频繁,因此您需要一个驱逐策略来优先考虑频繁访问的项目。适合该场景的两种缓存删除策略是:
•LRU 逐出策略:首先删除最近最少访问的项目。对于URL短链接服务来说,这种策略非常有效,因为它保证了最常访问的、最新的URL都保存在缓存中。这可以显着减少热门链接的访问时间。 • 或者,基于TTL 的逐出策略:为每个缓存条目分配固定的生存时间(TTL)。当条目的TTL 过期时,该条目将从缓存中删除。对于仅在短时间内流行的URL,TTL 策略对于URL 短链接服务很有用。
1*oDV7pndeZqmTmRrthz5a3Q.png
TTL还有助于自动更新缓存内容,并且可以与其他策略(例如LRU)结合使用,以更有效地管理缓存。
数据库扩展:结合复制和分片
为了确保您的数据库支持高可用性、容错性和可扩展性,您必须实施复制和分片策略。
考虑到7个字符集中有3.5T个唯一URL,我们可以使用基于键的分片将URL记录均匀分布在多个分片上。
假设分布在3 个分片上,每个分片存储大约1.16T 的URL。随着URL 数量的增加,这可以确保系统的可扩展性。
您还可以在每个分片内实现主/从复制,以确保高可用性和容错能力。此配置允许在节点发生故障时快速故障转移和恢复。
1*68H1bEHS3eYotv9dBy9hmg.png
此外,如果您的服务面向全球用户,您可以考虑地理分片和复制,以最大程度地减少延迟并改善不同区域的用户体验。
这种组合使该服务能够处理大量URL 缩短和重定向,几乎没有停机时间,并且响应时间更快。
1*XHmu-wQLQwyKAHztn3zIeA.png
安全考虑
我们服务的安全考虑因素包括:
•输入验证:用户提交的所有URL 都必须经过净化。您应该检查有效的协议(HTTP、HTTPS 等)并确保URL 的格式正确。这有助于防止注入攻击。 •速率限制:您可以通过限制来自单个源的请求数量来保护您的服务免受DDoS 攻击。考虑使用令牌桶算法。 •监控和日志记录:需要强大的日志系统(例如ELK堆栈)。这使您可以分析日志以查找瓶颈和可疑活动,以确保整体系统的健康状况。 • 混淆:您不希望短URL 被轻易预测。可以在生成算法中添加随机性,以防止攻击者猜测有效链接。 • 链接过期:您可以选择允许用户为缩短的URL 设置过期日期。这限制了潜在恶意链接的生命周期。
#以上关于系统设计:内容源网络涉及到URL短链接工具的设计,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92662.html