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

8 设计URL短链

前言

我们将解决一个有趣且经典的系统设计面试问题: 设计类似TinyURL的URL缩短器。

第一步 理解问题并确定设计的边界

候选人: 你能给一个URL缩短器如何工作的例子吗?
面 试 官 : 假 设
https://www.systeminterview.com/q=chatsystem&c=loggedin&v=v3&l=long 是
原URL,你的服务应该可以创建一个更短的URL(短链接): https://tinyurl.com/y7keocwj,
将其作为原URL的别名。如果点击这个短链接,它就可以把你重新导向至原URL。
候选人: 业务量有多大?
面试官: 每天要生成1亿个URL。
候选人: 短链接的长度是多少?
面试官: 越短越好。
候选人: 短链接中允许有哪些字符?
面试官: 短链接可以是数字(0~9)和字母(a~z、 A~Z)的组合。
候选人: 短链接可以被删除或者更新吗?
面试官: 为简单起见,我们假设短链接不能被删除或者更新。

以下是一些基本用例。

  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。

与面试官一起审查这些假设和估算很重要, 这样能确保你们俩对系统需求有相同的理解。

第二步 提出高层级的设计并获得认同

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

API端口

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

  1. 缩短URL。为了创建一个短URL,客户端会发送一个POST请求,它包含一个参数——原始的长URL。API看起来像下面这样:
POST api/v1/data/shorten
  • 请求参数: {longUrl: longURLString}。
  • 返回短URL。
  1. 重定向URL。为了把短URL重定向到对应的长URL,客户端会发送GET请求。API看起来像下面这样:
POST api/v1/shorturl

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

URL重定向

下图展示了当你在浏览器中输入一个经过缩短的TinyURL网址时会发生什么。一旦服务器收到一个TinyURL请求,就会通过301重定向把短URL换成长URL。
在这里插入图片描述
客户端和服务器之间的详细通信信息如下图所示。
在这里插入图片描述
301重定向: 意味着所请求的URL“ 永久” 移动到长URL。因为是永久重定向,所以浏览器会缓存该响应,以后对同一个URL的请求就不会发给URL缩短服务器了,而会将其直接重定向到长URL服务器。
302重定向: 意味着URL“ 暂时” 移动到长URL, 这也意味着对于同一个URL的后续请求会先发给URL缩短服务器,然后它们才会被重定向到长URL服务器。

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

实现URL重定向的最直观的方法就是使用哈希表。假设哈希表存储了:

  • 获取长URL: longURL=hashTable.get(shortURL)。
  • 一旦获取了长URL,就实施URL重定向。

缩短URL

我们假设短URL的格式为: www.tinyurl.com/{hashValue}。 为了支持URL缩短的使用场景,我们必须找到一个哈希函数fx,它可以把长URL(longURL)映射成哈希值。
在这里插入图片描述
这个哈希函数必须满足下面的要求:

  • 每个长URL必须可以通过哈希函数转换成一个哈希值(hashValue)。
  • 每个哈希值可以被映射回原始的长URL。

第三步 设计继续深入

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

数据模型

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

哈希函数

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

哈希值的长度
哈希值由数字(0~9)和字母(a~z、 A~Z)组成,包含62种可能的字符(10个数字+26个小写字母+26个大写字母=62)。 为了确定合适的哈希值长度,我们需要找到最小的n,使得62的n次幂小于或等于3650亿。根据之前的估算,系统需要支持高达3650亿个URL。下表展示了随n的变化其对应支持的最大URL数量。
在这里插入图片描述
当n=7时, 6276^{27}627≈3.5万亿,足够支持3650亿个URL,所以哈希值的长度应该是7位。
我们会探讨两种用于URL缩短器的哈希函数。第一种是“哈希+解决冲突” ,第二种是“Base 62转换” 。

哈希+解决冲突
为了缩短一个长URL,我们需要实现一个哈希函数将长URL哈希成7个字符的字符串。最直接的解决方案是使用那些有名的哈希函数,比如CRC32MD5或者SHA-1等。下表比较了对长 URL“https://en.wikipedia.org/wiki/Systems_design” 使用不同哈希函数的结果。
在这里插入图片描述
如上表所示,即使是最短的哈希值(通过CRC32算法得到)都太长了(超过7个字符) 。
怎么能让它变得短一些呢?
第一个方法是取哈希值的前7个字符,但是这个方法会导致哈希冲突(Hash Collision)。 为了解决哈希冲突,我们可以递归地添加一个新的预先设定好的字符串,直到不再发现冲突为止。 下图解释了这个过程。
在这里插入图片描述
这个方法可以消除哈希冲突,但是对每一个请求都要查询数据库以检查是否存在对应的短URL,这个成本是很高的。一种叫作布隆过滤器的技术可以提升性能。布隆过滤器是一种高效利用空间的概率性技术,可以用来检测一个元素是否属于某个集合。

Base 62转换
基数转换(Base Conversion)是被广泛用于URL缩短器的另一种方法。基数转换可以将同一个数字在不同的数值表示系统之间进行转换。用Base 62转换是因为一个哈希值中有62种可能的字符。下面用一个例子来解释如何进行转换:把1115710转换成Base 62的表示(1115710表示的是十进制数11,157)。
从名字可以看出,Base 62是一种使用62个字符来进行编码的方式。其映射关系为:0⟶00\longrightarrow000,…,9⟶99\longrightarrow99910⟶a10\longrightarrow a10a11⟶b11\longrightarrow b11b,…,35⟶z35\longrightarrow z35z36⟶A36\longrightarrow A36A,…,61⟶Z61\longrightarrow Z61Z,其中“a”代表10,“Z”代表61,依此类推。

1115710=2×622+55×621+59×620=[2,55,59],转换为Base 62的表示就是[2,T,X]。下图展示了转换过程。
在这里插入图片描述
因此,短URL就是https://tinyurl.com/2TX。

哈希+解决冲突Base 62转换
短URL长度固定短URL长度不固定,会随ID变化
不需要唯一ID生成器需要依赖唯一ID生成器
可能存在哈希冲突,并且必须解决不会有冲突,因为ID是唯一的
无法知道下一个可用的短URL是什么,因为它不依赖于ID如果新记录的ID会加1,那么很容易就知道下一个可用的短URL是什么。这可能是一个安全隐患

深入探讨URL缩短流程

作为系统的核心组成部分之一, UR L缩短流程应该是逻辑简单的,而且能提供我们想要的功能。在我们的设计里使用了Base 62转换。
在这里插入图片描述
这里,分布式唯一ID生成器值得一提。它主要的功能是生成全局唯一的ID, 这个ID被用来创建
短URL。在高度分布式的环境中, 实现唯一ID生成器是很有挑战性的。不过,我们已经讨论过一些解决方案。见传送门。

深入探讨URL重定向流程

下图展示了URL重定向的详细设计。因为读操作远多于写操作,所以:
在这里插入图片描述
URL重定向的流程总结如下:

  1. 用户点击一个短URL“https://tinyurl.com/zn9edcu”。
  2. 负载均衡器将请求转发给Web服务器。
  3. 如果短URL已经在缓存中,则直接返回对应的长URL。
  4. 如果短URL不在缓存中,则从数据库中获取对应的长URL;如果这个短URL不在数据库中,那么有可能用户输入了无效的短URL。
  5. 将长URL返回给用户。

第四步 总结

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

  • 限流器:恶意用户发送海量的URL缩短请求是系统可能遇到的一个安全问题。限流器可以帮助我们基于IP地址或者其他过滤条件来拦截请求。如果你想回顾关于流量限制的知识,见传送门。
  • Web服务器伸缩:因为网络层是无状态的,所以很容易通过添加或移除Web服务器来对网络层进行伸缩。
  • 数据库扩展:数据库复制和分片是常用的技术。
    • 数据分析: 对于业务而言,数据变得越来越重要。将数据分析解决方案整合到URL缩短
    器中可以帮助我们回答一些重要问题,比如“ 有多少用户点击了一个链接?”“ 他
    们是什么时候点击的?” 。
    • 可用性、一致性和可靠性。 这些概念是所有大型系统成功的关键。我们在第1章中详
    细讨论过它们, 请回顾这些内容。

后记

恭喜你已经看到这里了。 给自己一些鼓励。干得不错!

http://www.dtcms.com/a/349308.html

相关文章:

  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(二十) 文件、文件夹选择框、保存文件框
  • qt配置ros2环境,简单版本
  • Rust:变量、常量与数据类型
  • 2025 突出的时序模型
  • 【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day13
  • Linux-Redis的安装
  • 第四章:并发编程的基石与高级模式之Select语句与多路复用
  • 【Linux】开发工具命令指南:深度解析Vim的使用操作
  • Allegro17.4导出带有NET的PDF文档及组装样式图
  • MongoDB vs MySQL:NoSQL 和 SQL 的核心区别与适用场景
  • 前端开发:详细介绍npm、pnpm和cnpm分别是什么,使用方法以及之间有哪些关系
  • CPTS-Pressed复现(XML-RPC)
  • Python 面向对象进阶:深入理解封装、继承与多态
  • 【C++】第二十六节—C++11(中) | 右值引用和移动语义(续集)+lambda
  • 验证码流程
  • 【AMBA总线互联IP】
  • 6、RocketMQ消息积压问题如何解决
  • QSpinBox的用法及其使用QSS对其美化
  • 【ElasticSearch】json查询语法和可用的客户端
  • Docker 在线安装 RabbitMQ
  • 开源 C++ QT Widget 开发(五)通讯--串口调试
  • NILMTK(非侵入式负载监测工具包)安装
  • Linux 进阶之性能调优,文件管理,网络安全
  • AI精准种植改写农业格局:亩产量提升18%+水资源利用率提高32%,破解小农户技术门槛难题
  • Linux下usb设备驱动涉及的结构体
  • More Effective C++ 条款06: 区分自增自减操作符的前缀和后缀形式
  • 04-ArkTS编程语言入门
  • 分享些 Function 和 枚举的经典使用案例
  • 【RAGFlow代码详解-1】概述
  • 青少年软件编程(python六级)等级考试试卷-客观题(2023年3月)