相信你在生活中会收到很多短信,尤其是在最近的双十一活动期间,而那些短信有两个特点。第一个是几乎都是垃圾短信,这里可以忽略。第二个是链接很短,比如下面这个:
我们知道,有些短信是有字数限制的,直接放一个带各种参数的链接是不合适的。还有一点就是我们不想暴露参数。好处如下:
这背后的原理是什么?怎么发生的?你会如何设计这样一个系统?[来自鹅场采访者]
短链接的原理短链接展示的逻辑这里最重要的知识点是重定向。我们先来回顾一下http的状态码:
整个跳跃过程:
从下图可以看出,链接确实被302重定向到新地址,返回的头中有一个字段:Location是要重定向的地址:
当然,我们首先想到的是压缩。和文件压缩一样,压缩后我们解压还原到原链接,重定向到原链接。不幸的是,这是行不通的。你见过有什么压缩方法可以直接把这么长的数字压缩到这么短的长度?其实是不可能的。就像Huffman树一样,只能高效压缩重复字符多的字符串。像link可能需要很多参数,存在各种不规则性,直接压缩算法不现实。
https://dx.10086.cn/tzHLFw和https://gd.10086.cn/gmccapp/web page/pay phone money/index . html怎么样?channel=之间的交换是什么?前面的路径不变,变的是后面的路径,也就是tzHLFw和gmccapp/web page/payphonemoney/index . html?通道=之间的转换。
其实也很简单,就是数据库中的一段数据,一个id对应一个长链接(相当于一个全局发送者,一个全局唯一的ID):
单机的唯一ID很简单,AtomicLong可以用,分布式的不行。简单来说,可以用redis,或者自己增加数据库,或者可以考虑Zookeeper之类的。
id 转换策略但是直接使用递增的数字有两个缺点:
很明显,我们平时看到的链接不是数字,一般都是大小写字母加数字。为了缩短链接的长度,我们必须转换id。比如我们的短链接由a-z,A-Z,0-9组成,相当于62位,把id转换成62位:
public class short URL { private static final String BASE = & # 34;0123456789 abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz & # 34;; public static String to base 62(long num){ StringBuilder result = new StringBuilder(); do { int I =(int)(num % 62); result . append(base . charat(I)); num/= 62; } while(num & gt;0); return result.reverse()。toString(); } public static long to base 10(String str){ long result = 0; for(int I = 0;我& ltstr . length();i++){ result = result * 62+base . index of(str . charat(I)); } 返回结果; } public static void main(String[]args){ //tzHLFw system . out . println(to base 10(& # 34;tzHLFw & # 34)); system . out . println(to base 62(27095455234 l)); } } id转62位key或key转id已经实现,但是计算还是比较耗时,不如加一个字段保存,这样数据库就变成了:
一般短链接都有过期时间,所以我们还必须在数据库中添加相应的字段。在访问的时候,首先要判断它们是否过期,如果过期了,我们就不重定向了。
如果暴露了大量的短链接,数据库中有大量的数据,此时可以考虑使用缓存优化。生成的时候顺便把缓存写进去,然后读取的时候直接去缓存就行了,因为短链接和长链接的关系不会被修改,即使修改也是很低的频率。
系统的id用完了怎么办?这个概率很小。如果真的发生了,已经过期的旧身份证号可以重新使用。
如果有人疯狂要求一些不存在的短链接怎么办?其实这就是缓存渗透。缓存渗透意味着大量请求缓存和数据库中不可用的数据。例如,订单号不能为-1,但是用户请求订单号为-1的大量数据。因为数据不存在,所以数据不会存在于缓存中,所有请求都会直接穿透到数据库中。如果被恶意用户利用疯狂地请求不存在的数据,会导致数据库压力过大甚至崩溃。
针对这种情况,我们一般可以使用Bloom filter过滤掉不存在的数据请求,但是我们这里的id是内在递增有序的。其实我们的音域一般都是知道的,比较好判断。超出的部分肯定是不存在的,或者说请求到达时,在缓存中放一个空对象是没有问题的。
链接:面试官说:你可以设计一个短链接生成系统——第十六章——博客公园(cnblogs.com)









