系统设计实践篇的文章将会根据《系统设计面试的万金油》为前置模板,讲解数十个常见系统的设计思路。
设计目标设计一个像TinyURL这样的URL缩短服务。该服务将提供一个较短的URL,重定向到原本长的URL。
一. 为什么我们需要URL短链URL缩短用于为长URL创建更短的别名。我们称这些缩短的别名为短链接。当用户点击这些短链接时,它们会被重定向到原始URL。短链接在展示、打印、发送或发推时可以节省大量空间,而且便于用户手动输入。
例如,如果我们通过TinyURL缩短这个URL
https://www.educative.io/collection/page/5668639101419520/5649050225344512/5668600916475904/916475904
可以得到:
缩短后的网址几乎是实际网址的三分之一大小。
URL缩短用于优化跨设备的链接,跟踪单个链接以分析受众和活动表现,并隐藏关联的原始URL。
如果您以前没有使用过tinyurl.com,请尝试创建一个新的短网址,并花一些时间浏览他们提供的各种服务选项,对你理解有很大帮助。
二. 系统的需求与目标你应该在面试一开始就明确要求。一定要问问题,找出面试官脑海中系统的确切范围。
我们的网址缩短系统应该满足以下要求:
功能性需求:给定一个URL,我们的服务应该生成一个更短且唯一的别名。
当用户访问一个短链接时,我们的服务应该将他们重定向到原始链接。
用户应该能够选择一个自定义的短链接为他们的URL。
链接将在标准的默认时间间隔之后过期。用户应该能够指定过期时间。
非功能性需求:系统应该是高度可用的。这是必需的,因为如果我们的服务停止,所有的URL重定向将开始失败。
URL重定向应该实时发生,延迟最小。
缩短的链接不应该是可猜测的(不可预测的)。
扩展性需求:分析: 例如,发生了多少次重定向?
我们的服务也应该可以通过REST API被其他服务访问。
三. 容量估算与约束短链系统从请求读写量上来说,属于是读取量很大的。与缩短一个URL相比,访问短链将会有大量的重定向请求。可以假设读和写的比率是100:1。
流量估算假设我们每个月有 500M 的新 URL 缩短,读/写比为 100:1,我们可以预期在同一时期有 50B 的重定向。
100 * 500M => 50B
我们系统的每秒查询(QPS)是多少?
500 million / (30 days * 24 hours * 3600 seconds) = ~200 URLs/s
考虑到 100:1 的读/写比率,每秒 URL 重定向将是:
100 * 200 URLs/s = 20K/s
存储估计假设我们将每个URL目标链接(以及相关的缩短链接)存储5年。因为我们预计每个月有5亿个新url,所以我们预计存储的对象总数将达到300亿个
500 million * 5 years * 12 months = 30 billion
让我们假设每个存储对象大约为500字节(这只是一个粗略的估计,我们稍后将深入研究),我们总共需要15TB的存储空间。
带宽估计对于写请求,由于我们预计每秒有200个新url,所以我们服务的总传入数据将是每秒100KB
200 * 500 bytes = 100 KB/s
对于读请求,由于我们预计每秒钟有大约20K的url重定向,所以我们的服务的总输出数据将是每秒10MB
20K * 500 bytes = ~10 MB/s
内存估计如果我们想缓存一些经常被访问的热点url,我们需要多少内存来存储它们?
如果我们遵循80-20原则,即20%的url产生80%的流量,我们希望缓存这些20%的热点url。
由于我们每秒有2万次请求,我们每天将会收到17亿次请求。
20K * 3600 seconds * 24 hours = ~1.7 billion
要缓存20%的请求,我们需要170GB内存。
0.2 * 1.7 billion * 500 bytes = ~170GB
这里需要注意的一点是,由于会有很多重复的请求(相同的URL),因此,我们的实际内存使用量将少于170GB。
估算概述假设每个月有5亿个新url,读:写比率为100:1,下面是对我们服务容量估算的总结。
创建短链 200/s
短链重定向 20K/s
入口流量 100KB/s
出口流量 10MB/s
五年需要存储量 15TB
内存用量 170GB
四. 系统API设计一旦我们确定了需求,定义系统API总是一个好主意。这时候应该明确说明系统期望做到什么。
我们可以使用SOAP或REST API来公开服务的功能。下面是用于创建和删除url的api的定义。
createURL(api_dev_key, original_url, custom_alias=None, user_name=None, expire_date=None)
参数api_dev_key (string) : 注册帐号的api开发密钥。此外,这将用于根据用户分配的配额限制用户
original_url (string): 可选的短链地址
custom_alias (string) : URL 的可选自定义键
user_name (string) : 用于编码的可选用户名
*• expire_date (string) : 可选的过期时间
成功将返回缩短的URL。否则,它将返回错误代码。
deleteURL(api_dev_key, url_key)
其中url键是一个字符串,表示要检索的缩短的url。成功的删除返回URL Removed。
我们如何发现和预防滥用?