【场景题】如何设计一个短链系统
【场景题】如何设计一个短链系统
- 1. 前言
- 2. 短链原理
- 3. 唯一短链生成
1. 前言
我平时经常看极客时间上的专栏,上面的每一个专栏 URL 地址都有一个短链与之对应。比如你使用下面两个链接打开的都是《MySQL实战45 讲》这门课程。
原始链接:https:/time.geekbang.org/column/intro/100020801
短链:http://gk.link/a/10q2l
有了长链,为什么还要再弄一个短链呢?
1.短链更简洁,更方便传播:过长的链接不利于在互联网传播;
2.方便对链接的点击情况做后续追踪:比如查看短链最近一周的访问量、访客数、访问来源…
3.对于短信等限制字数的场景来说更加友好:很多社交平台发表动态是有字数限制的,如果你直接使用长链的话,那留给你自己想表达的其他内容的文字就少了很;
4.……
2. 短链原理
短链的具体原理其实比较简单,说白了就是:通过短链找到长链(原始链接),然后再重定向到长链地址即可!
举个例子:我们来访问 http://gk.link/a/10q2l 这个链接,从 HTTP 请求信息可以看到请求被重定向了,返回的状态码为 “302”
另外还有一个比较常用的重定向状态“301”,我们应该用“301”还是“302”作为状态码更好呢?
答案是:“302”,绝大部分短链系统也都是使用的“302”作为状态码。
这是因为 “301”状态码代表永久重定向,只要浏览器拿到长链之后就会对其缓存,下次再请求短链就直接从缓存中拿对应的长链地址。这样的话,我们就没办法对短链进行相关分析了。
而“302”状态码代表资源被临时重定向了,不会存在上面说的这种问题。
举个例子:你的活动链接通过短链发送给了 10w+用户,你想知道短链后续的点击情况的话,你使用“301”状态码就不行了。
3. 唯一短链生成
原始链接必定是唯一的,我们也要确保生成的短链唯一。
如何生成唯一的短链呢?换言之就是我们如何通过唯一的字符串来表示长链。
比较常见的一种方法就是:通过哈希算法对长链去哈希。
一般建议使用用非加密型哈希算法比如 MurmurHash。因为,相比于 MD5,SHA 等加密型哈希算法,非加密型哈希算法往往效率更高!
我们拿 MurmurHash 来说, MurmurHash 当前最新的版本是 MurmurHash3,它能够产生出32-bit 或 128-bit 哈希值。对于绝大部分场景来说,32-bit 的一般就已经够用了。
生成的哈希值是 10 进制的,为了缩短它的长度,我们可以将其转变为 62 进制即可。10 进制的 3394174629 转换为 62 进制就是 3HHBS5。
我们将 3HHBS5 作为短链的唯一标识拼接即可。
既然使用了哈希算法,那不可避免会出现哈希冲突(不同的长键生成的短链是一样的),虽然概率比较小,但是我们也还是要解决。
如何判断是否发生了哈希冲突呢?
判断是否发生哈希冲突也就是看我们生成的短链是否是唯一的。
如果我们使用的是 MysQL,PostgreSQL 这类关系型数据库的话,我们可以给存放短链的字段 sort_ur1 添加唯一索引。不过,为了提高性能以及应对高并发,还是建议利用布隆过滤器解决这个问题。