请求流程
举例:当当的短链接
http://dwz.win/nXR
,它是由两个部分组成
http://dwz.win
:短链接系统的域名地址
nXR
:请求参数请求
http://dwz.win/nXR
地址后,返回状态如下所示
功能分析
三个功能
- 发号,存储,映射
可以分为两个模块:发号与存储模块、映射模块
发号与存储模块
- 发号:使用发号器发号,为每个长地址分配一个号码ID
- 并且需要防止地址二义,也就是防止同一个长址多次请求得到的短址不一样
- 存储:将号码与长地址存放在DB中,将号码转化成62进制
- 用于表示最终的短地址,并返回给用户
映射模块
用户使用62进制的短地址请求服务
- 转换:
- 将62进制的数转化成10进制
- 映射:在DB中寻找对应的长地址
- 通过302重定向,将用户请求重定向到对应的地址上
短地址算法原理
采用六十二进制表示法!
其中核心的部分 EYyCO9T 只有7位长度。
- 这里的7位长度是使用62进制来表示的
- 就是常用的0-9、a-z、A-Z,也就是10个数字+26个小写+26个大写=62位。
7位长度62进制可以表示多大范围呢?
62^7 = 3,521,614,606,208 (合计3.5万亿)
10进制 最大只能生成 10 ^ 6 - 1 =999999个
16进制 最大只能生成 16 ^ 6 - 1 =16777215个
16进制里面已经包含了 A B C D E F 这几个字母
62进制 最大能生成 62 ^ 6 - 1 =56800235583个
短网址的长度,可以根据自己需要来调整,如果需要更多,可以增加位数
- 6位长度
62^6
能达到568亿的范围
private static final String BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static String toBase62(long num) {
StringBuilder sb = new StringBuilder();
do {
int i = (int) (num % 62);
sb.append(BASE.charAt(i));
num /= 62;
} while (num > 0);
return sb.reverse().toString();
}
全局发号器
分布式ID生成算法!
表结构
列名 | 说明 |
---|---|
id | BIGINT,自增主键 |
key | 短串,需要加唯一索引 |
url | 长地址,需要跳转的原地址 |
相同的原始网址可能会对应不同的短链
每次新来一个原始网址,就生成一个新的短链:
- 这种做法就会导致两个相同的原始网址生成了不同的短链。
第一种处理思路是:
- 不做处理,实际上,相同的原始网址对应不同的短链,这个用户是完全可以接受的。
第二种处理思路是:
- 拿原始网址在数据库中查找,看数据库中是否已经存在相同的原始网址了。
- 如果数据库中存在,那就取出对应的短链,直接返回给用户。
- 这种处理思路需要给数据库中的短链和原始网址这两个字段,都添加索引。
- 这是有代价的:
- 一方面两个索引会占用更多的存储空间。
- 另一方面索引还会导致插入、删除等操作性能的下降。