李智慧 · 高并发架构实战课
李智慧
同程艺龙交通首席架构师,前 Intel & 阿里架构师,《大型网站技术架构》作者
23286 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 26 讲
李智慧 · 高并发架构实战课
15
15
1.0x
00:00/00:00
登录|注册

03 | 短 URL 生成器设计:百亿短 URL 怎样做到无冲突?

实际并发压力:200
2万QPS,10ms平均响应时间
解决方案:长URL与短URL映射关系缓存
改造标准Base64编码以适应URL
检查数据库中的冲突
限制长度,避免与预生成短URL冲突
预加载服务器从HDFS加载短URL
文件格式:直接存储短URL ASC码
存储在HDFS
海量数据存储:HDFS和HBase
分布式缓存
负载均衡
预生成短URL
自增长短URL
单项散列函数
短URL不可预测性
高性能
高可用性
短URL长度:6个字符
网络带宽:高峰期320Mb
吞吐量:平均2万QPS,高峰期4万QPS
存储容量:120亿条短URL,约12TB存储空间
提供后台管理界面
支持自定义短URL
重定向短URL到原始长URL
将长URL转换为短URL
提出设计文档评审意见
分享思考
并发量计算
问题:重复长URL生成不同短URL
URL Base64编码
用户自定义短URL
短URL预生成文件及预加载
重定向响应码:302临时重定向
部署模型
短URL生成算法
非功能需求
性能指标
短URL生成器功能
评审意见
思考题
详细设计
概要设计
需求分析
短URL生成器设计总结

该思维导图由 AI 生成,仅供参考

你好,我是李智慧。
从这节课开始,我们将结合具体的案例,来看看怎么设计高并发系统,你也可以学习具体的软件设计文档写法了。这个模块,我们先来看看,当高并发遇到海量数据处理时的架构。
在社交媒体上,人们经常需要分享一些 URL,但是有些 URL 可能会很长,比如:https://time.geekbang.org/hybrid/pvip?utm_source=geektime-pc-discover-banner&utm_term=geektime-pc-discover-banner
这样长的 URL 显然体验并不友好。我们期望分享的是一些更短、更易于阅读的短 URL,比如像 http://1.cn/ScW4dt 这样的。当用户点击这个短 URL 的时候,可以重定向访问到原始的链接地址。为此我们将设计开发一个短 URL 生成器,产品名称是“Fuxi(伏羲)”。
我们预计 Fuxi 需要管理的短 URL 规模在百亿级别,并发吞吐量达到数万级别。这个量级的数据对应的存储方案是什么样的?用传统的关系数据库存储,还是有其他更简单的办法?此外,如何提升系统的并发处理能力呢?这些是我们今天要重点考虑的问题。

需求分析

短 URL 生成器,也称作短链接生成器,就是将一个比较长的 URL 生成一个比较短的 URL,当浏览器通过短 URL 生成器访问这个短 URL 的时候,重定向访问到原始的长 URL 目标服务器,访问时序图如下。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

设计高并发、海量数据处理的短 URL 生成器方案 本文介绍了设计一个高并发、海量数据处理的短 URL 生成器的方案。首先分析了需求和性能指标,预计每月新生成短 URL 5亿条,短 URL 总数达到120亿,对存储容量和吞吐量进行了估算。在概要设计中,提出了三种短 URL 生成算法:单项散列函数生成短 URL、自增长短 URL 和预生成短 URL。最终选择了预生成短 URL 的方案,通过离线生成并存储在文件系统中的方式,避免了冲突处理和性能问题。文章详细介绍了每种算法的优缺点,并对系统的非功能需求进行了说明,包括高可用性、高性能和短 URL 的不可猜测性。整体设计思路清晰,为读者提供了设计高并发系统的实际案例,对软件设计文档的写作也进行了指导。文章还介绍了 Fuxi 的整体部署模型,包括高并发读请求处理、预生成短 URL 存储以及访问的详细设计。文章内容丰富,涵盖了系统架构、存储、缓存、性能优化等方面,对于需要设计高并发系统的读者具有一定的参考价值。 Fuxi是一个高并发(2万QPS)、海量存储(144亿条数据)、还需要10ms的高性能平均响应时间的系统。但是Fuxi的架构并不复杂。Fuxi的业务逻辑简单,只需要完成短URL与长URL的映射关系生成与获取。开源技术体系的成熟,如HDFS集群和Redis缓存,为Fuxi提供了高可用的数据存储解决方案和短平均响应时间。文章还提出了思考题,探讨了用户重复提交同一个长URL请求生成短URL可能导致的问题以及解决方案,以及如何得到真正的并发量200的问题。 文章内容丰富,涵盖了系统架构、存储、缓存、性能优化等方面,对于需要设计高并发系统的读者具有一定的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《李智慧 · 高并发架构实战课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(53)

  • 最新
  • 精选
  • 向东是大海
    短URL使用URL Base64 编码,其中的-和_字符显得有点突兀,特别是在开头或结尾是时。短URL使用Base62编码是否更好?

    作者回复: 赞,很好的意见。

    2022-02-21
    39
  • 老码不识途
    再加一个架构的约束:只有2万块钱的预算 ^_^

    作者回复: 大佬,请上座。

    2022-02-21
    3
    39
  • Aibo
    个人感觉内存中存储短url的数据结构是不是用环形数组会好一点. 短url的场景下,使用链表会有两个缺点 1. gc压力大,频繁申请内存空间 2.格外的指针开销,短url才6byte,指针就占1byte,也就是内存中10g数据1个多g都是指针

    作者回复: 赞,非常好的建议

    2022-03-05
    6
    32
  • Spark
    对自增长短 URL可以进行如下优化: 在设计的短链接的时候采用这样的方法: 根据自增主键id将前面补0(4位短链接补至7位,6位短链接补至10位,8位短链接补至14位)如主键:123,补0至0000123 倒转补完0之后的id,如3210000 将倒转之后的短链接十进制转62进制。将3210000转62进制 本质上来讲,因为用户不知道你补位的位数,所以无法反推出你之前的短链接与之后的短链接。 在自增的选择上,可以选择redis的自增机制。 是不是这样,我也可以满足并发的需求,毕竟计算速度远大于查找。 同时,清理的过程也更加简单,只需要在达到自增补位上限的时候,将自增变为1重新发号即可 当然,从技术上讲,他是可预测的,毕竟短链就这么多位,猜测(7-14进行枚举),但是面对大部分业务来说,他已经满足部分不可预测的需求。

    作者回复: 很赞

    2022-02-22
    6
    28
  • Jialin
    问题一:如何解决相同的原始链接生成不同的短链接? 当要给一个原始网址生成短网址的时候,我们要先拿原始网址在数据库中查找,看数据库中是否已经存在相同的原始网址了。如果数据库中存在,那我们就取出对应的短网址,直接返回给用户。并给短网址和原始网址这两个字段,都添加索引。短网址上加索引是为了提高用户查询短网址对应的原始网页的速度,原始网址上加索引是为了加快通过原始网址查询短网址的速度。 问题二:并发量是如何计算的? 基于利特尔法则(Little's law)得知,并发度 = QPS * 平均耗时,所以,2 万 QPS,10ms 平均响应时间,真正的并发量只有 200。

    作者回复: 1 索引的代价有点大的,我们再考虑下 2 是的

    2022-02-21
    7
    15
  • Mew151
    第1个问题,还可以从另外一个角度考虑:即客户端本地记用户请求过的长-短URL映射,如果用户再次请求同一个长URL,先查客户端本地映射,如果有就直接返回。这种方式能防住大部分正常的客户端重复请求,防不住的是例如恶意攻击者直接抓包调接口,因此服务端的判重还得做。

    作者回复: 赞

    2022-03-09
    12
  • 雪碧心拔凉
    看了下评论区的,大部分都是通过布隆过滤器来解决不能重复,有一下几个疑惑点。 1、已使用的数据还会被回收,因此布隆过滤器的数据还存在删除的操作,或者每次回收时重构布隆过滤器? 2、布隆过滤器本身有一定的误判率,如果存在,但是实际可能不存在,这时要走生成的逻辑,请求耗时可能大于10ms。当然这个可以通过调整布隆过滤器的参数降低概率 我理解是不是只需要保持一段时间内不重复即可,是否可以把长url(做个md5,降低存储?)和短url存储在缓存(如redis)中,有效期设为一天或者半天,这样能控制一段时间内返回同一个短url即可?

    作者回复: 赞同

    2022-05-10
    10
  • 极客
    加载到预加载短 URL 服务器的 1 万个短 URL 会以链表的方式存储,每使用一个短 URL,链表头指针就向后移动一位,并设置前一个链表元素的 next 对象为 null。这样用过的短 URL 对象可以被垃圾回收。当剩余链表长度不足 2000 的时候,触发一个异步线程,从文件中加载 1 万个新的短 URL,并链接到链表的尾部 ----- 这里如果为了高可用是不是需要保存到日志或者redis,要是服务有bug导致频繁重启,那么重启后又要获取1万个。多来几次会浪费很多短地址没有使用。且预生成的144亿次没有继续生成的机制保证。

    作者回复: 预生成多20%的冗余,一般重启丢失一些是可以接受的,频繁重启可能系统有大麻烦了,需要另外思考了。 继续生成机制可以在系统运行期考虑,如果短URL消耗快于预期,可以增加再生成机制。架构不必一步到位。

    2022-02-21
    4
    10
  • Steven
    思考题: 1,首先可以明确,一定程度上的重复生成是可以的。 方案一:可以考虑用布隆过滤器; 方案二:考虑Redis中存储长链接 -> 短链接,并设定合理的过期时间,参考课程内容,貌似可以6天,或许1小时就可以。 另外,基于分布式ID生成短URL也是可以的。 2,200 = 20000 * 0.01 问题:“对于这样简单的业务逻辑以及 200 这样的并发压力,我们使用配置高一点的服务器的话,只需要一台短 URL 服务器其实就可以满足了。”,大概是一台什么配置的服务器?

    作者回复: 思考题:赞 市面上标配的高CPU物理机就可以了。其实可能都不用高配,随便什么服务器都够用了,主要是开发的时候响应时间要能做到10ms。

    2022-03-03
    2
    8
  • cy_walker
    老师,我有个疑问。就是在生成短链的时候,假如在短时间内有大量需要生成短链的请求,那预先加载的1W个短链就不够了,这种情况该如何解决?直接服务降级?

    作者回复: 1 预加载短URL的线程是异步执行的,短URL少于2000就会加载,加载时间顺利的话几十毫秒,这个响应速度应该是能够满足高并发的。 2 预加载短URL服务器也是集群部署的,每台服务器预加载1万个。 3 如果并发超过以上两点的处理能力,需要限流。

    2022-03-02
    2
    8
收起评论
显示
设置
留言
53
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部