当前位置: 首页 > article >正文

面试场景题系列:设计URL短链

1.场景需求界定

1.缩短URL:提供一个长URL,返回一个短很多的URL。

2.重定向URL:提供一个缩短了的URL,重定向到原URL。

3.高可用、可扩展性和容错性考量。

•写操作:每天生成1亿个URL。

•每秒的写操作数:1亿÷24÷3600≈1160。

•每秒的读操作数:假设读操作与写操作的比例是10∶1,那么每秒的读操作数是1160×10=11,600。

•假设URL缩短器会运行10年,这意味着我们必须支持1亿×365×10=3650亿条记录。

•假设URL的平均长度是100个字符,那么10年的存储容量需求是:3650亿×100字节≈36.5TB。

2.顶层设计

在这一节,我们将讨论API端点、URL重定向和URL缩短的相关流程。

2.1 API端点

API端点有利于客户端和服务器之间的通信。我们会把API设计成REST风格。如果你不熟悉REST风格的API,可以参阅一些文章,比如RestapiTutorial网站上的文章。一个URL缩短器主要需要两个API端点。

1.缩短URL。为了创建一个短URL,客户端会发送一个POST请求,它包含一个参数——原始的长URL。API看起来像下面这样:

POST api/v1/data/shorten

•请求参数:{longUrl:longURLString}。

•返回短URL。

2.重定向URL。为了把短URL重定向到对应的长URL,客户端会发送GET请求。API看起来像下面这样:

POST api/v1/shorturl

返回长URL以进行HTTP重定向。

2.2 URL重定向

图-1展示了当你在浏览器中输入一个经过缩短的TinyURL网址时会发生什么。

一旦服务器收到一个TinyURL请求,就会通过301重定向把短URL换成长URL。

客户端和服务器之间的详细通信信息如图-2所示。

图-2

**301重定向:**意味着所请求的URL“永久”移动到长URL。因为是永久重定向,所以浏览器会缓存该响应,以后对同一个URL的请求就不会发给URL缩短服务器了,而会将其直接重定向到长URL服务器。

**302重定向:**意味着URL“暂时”移动到长URL,这也意味着对于同一个URL的后续请求会先发给URL缩短服务器,然后它们才会被重定向到长URL服务器。

每种重定向方法都有自己的优缺点。如果降低服务器的负载是需要优先考虑的事项,使用301重定向就是合适的,因为对于同一个URL只有第一次请求会被发到URL缩短服务器上。但是如果数据分析很重要,那么302重定向就是更好的选择,因为它可以更轻松地跟踪点击率和点击来源。

实现URL重定向的最直观的方法就是使用哈希表。假设哈希表存储了<shortURL,longURL>键值对,可以通过以下步骤实现URL重定向。

•获取长URL:longURL=hashTable.get(shortURL)。

•一旦获取了长URL,就实施URL重定向。

2.3 缩短URL

我们假设短URL的格式为:www.tinyurl.com/{hashValue}。为了支持URL缩短的使用场景,我们必须找到一个哈希函数fx,它可以把长URL(longURL)映射成哈希值,如图-3所示。

图-3

这个哈希函数必须满足下面的要求:

•每个长URL必须可以通过哈希函数转换成一个哈希值(hashValue)。

•每个哈希值可以被映射回原始的长URL。

我们将在第3节探讨哈希函数的详细设计。

3. 设计继续深入

到目前为止,我们讨论了URL缩短和URL重定向的高层级设计。在本节中,我们会深入探讨以下内容:数据模型、哈希函数、URL缩短和URL重定向。

3.1 数据模型

在高层级设计中,所有的数据都被存储在哈希表中。这是一个很好的起点,但是在现实世界中内存资源是有限且昂贵的,因此这个方法并不可行。更好的选择是在关系型数据库中存储

图-4

3.2 哈希函数

哈希函数用于将长URL哈希成短URL,这个短URL也叫作哈希值(hashValue)。

哈希值的长度

哈希值由数字(0~9)和字母(a~z、A~Z)组成,包含62种可能的字符(10个数字+26个小写字母+26个大写字母=62)。为了确定合适的哈希值长度,我们需要找到最小的n,使得62的n次幂小于或等于3650亿。根据之前的估算,系统需要支持高达3650亿个URL。表8-1展示了随n的变化其对应支持的最大URL数量。

表-1

当n=7时,627≈3.5万亿,足够支持3650亿个URL,所以哈希值的长度应该是7位。

我们会探讨两种用于URL缩短器的哈希函数。第一种是“哈希+解决冲突”,第二种是“Base 62转换”。下面我们逐一来看一下。

为了缩短一个长URL,我们需要实现一个哈希函数将长URL哈希成7个字符的字符串。最直接的解决方案是使用那些有名的哈希函数,比如CRC32、MD5或者SHA-1等。下面的表8-2比较了对长URL“https://en.wikipedia.org/wiki/Systems_design”使用不同哈希函数的结果。

表-2

如表-2所示,即使是最短的哈希值(通过CRC32算法得到)都太长了(超过7个字符)。怎么能让它变得短一些呢?第一个方法是取哈希值的前7个字符,但是这个方法会导致哈希冲突(Hash Collision)。

为了解决哈希冲突,我们可以递归地添加一个新的预先设定好的字符串,直到不再发现冲突为止。图-5解释了这个过程。

图-5

这个方法可以消除哈希冲突,但是对每一个请求都要查询数据库以检查是否存在对应的短URL,这个成本是很高的。一种叫作布隆过滤器的技术可以提升性能。布隆过滤器是一种高效利用空间的概率性技术,可以用来检测一个元素是否属于某个集合。参考维基百科中“Bloom Filter”词条的相关介绍,可以了解更多细节。

Base 62转换

基数转换(Base Conversion)是被广泛用于URL缩短器的另一种方法。基数转换可以将同一个数字在不同的数值表示系统之间进行转换。用Base 62转换是因为一个哈希值中有62种可能的字符。下面用一个例子来解释如何进行转换:把1115710转换成Base 62的表示(1115710表示的是十进制数11,157)。

•从名字可以看出,Base 62是一种使用62个字符来进行编码的方式。其映射关系为:0→0,…,9→9,10→a,11→b,…,35→z,36→A,…,61→Z,其中“a”代表10,“Z”代表61,依此类推。

•1115710=2×622+55×621+59×620=[2,55,59],转换为Base 62的表示就是[2,T,X]。图-6展示了转换过程。•因此,短URL就是https://tinyurl.com/2TX

图-6

表-3展示了两种方法的不同点。

表-3

3.3 深入探讨URL缩短流程

作为系统的核心组成部分之一,UR L缩短流程应该是逻辑简单的,而且能提供我们想要的功能。在我们的设计里使用了Base 62转换。图-7展现了这个流程。

1.长URL是输入。

2.系统检查数据库中是否有这个长URL。

3.如果有,则意味着这个长URL此前曾经被转换为短URL。在这种情况下,从数据库中获取短URL并返回给客户端。

4.如果没有,则说明这是一个新的长URL。系统通过唯一ID生成器生成新的唯一ID(主键)。5.采用Base 62转换把这个ID转换成短URL。

6.创建一个新的数据库记录,其中包含ID、短URL和长URL。

为了更好地理解这个流程,我们来看一个具体的示例。

•假设输入的长URL是https://en.wikipedia.org/wiki/Systems_design。

•唯一ID生成器返回的ID为2009215674938。

•用Base 62转换把ID转成短URL,即ID(2009215674938)被转换成“zn9edcu”。

•将ID、短URL和长URL保存到数据库,如表-4所示。

这里,分布式唯一ID生成器值得一提。它主要的功能是生成全局唯一的ID,这个ID被用来创建短URL。在高度分布式的环境中,实现唯一ID生成器是很有挑战性的。

3.4 深入探讨URL重定向流程

图-8展示了URL重定向的详细设计。因为读操作远多于写操作,所以

图-8

URL重定向的流程总结如下:

1.用户点击一个短URL“https://tinyurl.com/zn9edcu”。

2.负载均衡器将请求转发给Web服务器。

3.如果短URL已经在缓存中,则直接返回对应的长URL。

4.如果短URL不在缓存中,则从数据库中获取对应的长URL;如果这个短URL不在数据库中,那么有可能用户输入了无效的短URL。

5.将长URL返回给用户。

4 总结

在本文中,我们讨论了API设计、数据模型、哈希函数、URL缩短和URL重定向。如果在面试的最后还有多余的时间,以下是一些可以讨论的议题。

•限流器:恶意用户发送海量的URL缩短请求是系统可能遇到的一个安全问题。限流器可以帮助我们基于IP地址或者其他过滤条件来拦截请求。如果你想回顾关于流量限制的知识,可以参考第4章。

•Web服务器伸缩:因为网络层是无状态的,所以很容易通过添加或移除Web服务器来对网络层进行伸缩。

•数据库扩展:数据库复制和分片是常用的技术。

•数据分析:对于业务而言,数据变得越来越重要。将数据分析解决方案整合到URL缩短器中可以帮助我们回答一些重要问题,比如“有多少用户点击了一个链接?”“他们是什么时候点击的?”。•可用性、一致性和可靠性。这些概念是所有大型系统成功的关键。我们在第1章中详细讨论过它们,请回顾这些内容。


http://www.kler.cn/a/456356.html

相关文章:

  • 小程序配置文件 —— 14 全局配置 - tabbar配置
  • meshy的文本到3d的使用
  • C++软件设计模式之责任链模式
  • 细说STM32F407单片机通过IIC读写EEPROM 24C02
  • 抖去推碰一碰系统技术源码/open SDK转发技术开发
  • SuperMap iClient3D for Cesium等高线标注
  • 深度学习中的参数初始化
  • Anaconda 安装与虚拟环境创建完整指南
  • jetbrains HTTPS 请求与响应流量分析报告【二】
  • C语言实践中的补充知识 Ⅶ
  • 在国产电脑上运行PDFSAM软件使用pdf分割合并交替混合处理pdf文档
  • 基于 Vant UI + Redisson BitSet 实现签到日历
  • springBoot发布https服务及调用
  • 77、将adaface的mtcnn模型npy文件转成atlas310p模型,并进行推理
  • 【Linux网络编程】第十五弹---传输层深度解析:端口号划分、UDP协议特性与TCP协议全面剖析(含连接管理、流量控制、拥塞控制等)
  • ShenNiusModularity项目源码学习(6:访问控制)
  • 设计一个基于Spring Boot开发的电商网站,部署在阿里云上
  • 【C/C++】C语言编程规范
  • pthread_create概念和使用案例
  • DeepSeek-V2:强大、经济且高效的专家混合语言模型
  • AIDD - 人工智能药物设计 -使用 Butina 模块对相似化合物进行聚类
  • vue2前端导出pdf文件
  • stm32基础(keil创建、Proteus仿真、点亮LED灯,7段数码管)
  • AI + 爬虫:智能化数据采集的未来
  • 转义特殊token is all you need
  • 已有docker镜像构建过程分析