什么是短网址系统?
我们在互联网时代,需要通过 URL 来访问一个指定的资源,可能是一个 HTML 页面也可能是一个图片、视频等等。域名被访问后,会经过DNS最终解析到一个具体的IP及端口上。
但是,因为资源层级很深,可能我们要访问的 URL 是:
http://www.zenworld.com/2022/01/01/page?id=12345
这个URL 很长,这个时候如果有短网址系统,我们可能可以转化为:
http://www.short.com/j8ve55y
看吧,URL 缩短了很多。 那么,缩短URL有什么好处呢:
方便用户记忆短信链接等场景,减短链接地址避免占用短信长度简化二维码链接,使得手机扫二维码精确度更高(信息少了)
所以短链一般也作为一个平台基础能力对外开放。
核心思路
哈希函数
首先我们需要一个Hash函数用于将具体的URL映射为一个唯一的别名,这个 Hash 函数的实现方式比较多,比如常见的 CRC32 。
F(URL) = 新的别名
存储
我们可以用关系型数据库比如MySQL来存储关联关系,例如:
ID,原始URL
j8ve55y,http://www.zenworld.com/2022/01/01/page?id=12345
重定向
服务端处理后取到新的地址后,返回 HTTP 请求,状态码写入302(重定向)以及在Header的Location字段里写入新的 URL 地址。
整体的请求实现如图所示:
优化措施
上面的方案可以直接使用了,并且上线后应对大部分的场景基本也能取得不错的表现,不过当请求、存储量级不断上升后,可能就会出现一些难以把控的问题了。
请求量级
因为短链系统是作为请求的第一环的业务基础系统,那么流量可能会非常高。如果大量的请求全部打到关系型数据库上,可能会有可用性问题。
优化的措施是:
关系型数据库(假设是MySQL)开启主从同步,业务读优先读从库,这样分摊了一定的压力加入缓存层,比如Redis,读可以先读缓存读不到再读数据库评估量级,如果量级不大可以直接使用 Redis 来存储 + 缓存,可显著降低时延且实现简单
存储量级
当数据量很大后,我们使用 uuid 作为mysql主键插入的成本会越来越高,因为ID不是连续的,插入时需要查询最新的这个 id 是在哪一页,并且可能有页分裂的风险。如果采用自增id,插入时可以直接插入到最后一页。因此为了插入性能优化,我们可以使用自增id作为id的生成算法。
不过性能提升的代价是牺牲了灵活性,比如业务上可能可以支持用户自定义短链地址,那么使用 uuid 的模式主键id 可以直接作为用户配置的 id 存储,因此最终是否需要使用自增id我们应该整体权衡业务的诉求以及存储量级。
总结
短连接系统的实现并不复杂,理解一下简单的HTTP 302重定向机制,存储一下URL Hash映射结果就可以实现。当然,在业务诉求中可能还会引入很多其他的业务改造,比如允许用户自定义地址,定时失效等等。
最后是关于存储选型,我这里给出的建议是 redis 或 mysql,也可以尝试组合使用,当然具体使用哪种存储要看业务的定位、量级来决策,我们在做系统设计上切勿脱离了实际的业务。
希望对你的工作有帮助!