目录
1.问题一:长链的关系和短链的关系是一对一还是一对多?
一个长链,在不同情况下(抖音推广、快手、短视频),生成的短网址应该不一样,才不会造成冲突,多渠道推广下,也可以区分统计不同渠道的效果质量
所以是 一个短链接只能对应一个长链接,当然一个长链接可以对应多个短链接(比如:一个长连接可对应抖音、朋友圈、快手的各个短链)。一短对一长,一长可以对应多个短。
2.问题二:前端访问短链是如何跳转到对应的页面的?
一种是服务端转发
由服务器端进行的页面跳转,刚学Servlet时, 从OneServlet中转发到TwoServlet
地址栏不发生变化,显示的是上一个页面的地址
请求次数:只有1次请求
转发只能在同一个应用的组件之间进行,不可以转发给其他应用的地址。所以在短链中不可用。 request.getRequestDispatcher("/two").forward(request, response);
还有一种是页面的跳转-重定向
由浏览器端进行的页面跳转
重定向涉及到3xx状态码,访问跳转是301还是302,301和302代表啥意思?
301 是永久重定向 会被浏览器硬缓存,第一次会经过短链服务,后续再访问直接从浏览器缓存中获取目标地址
好处:短地址一经生成就不会变化,所以用 301 是同时对服务器压力也会有一定减少
坏处:但是如果使用了 301,无法统计到短地址被点击的次数
302 是临时重定向 不会被浏览器硬缓存,每次都是会访问短链服务
所以选择302虽然会增加服务器压力,但是有很多数据可以获取进行分析
最后选择使用302,这个也可以对违规推广的链接进行实时封禁
3.问题三:短链码如何是如何生成的
短链码需要有的特点:
1.生成性能强
2.碰撞概率低
3.避免重复
4.恶意猜测、业务规则安全
解决方式一:业界用的比较多的是自增ID
利用插入数据库,利用数据库自增id
把自增id转成62进制作为短链码
短链码的长度不固定,随着 id 变大,短链码长度也增长
可以指定从某个长度开始增长,到百亿、千亿数量
转换工具:https://tool.lu/hexconvert/
是否存在重复: 不重复
但短链码是有序的递增,存在【业务数据安全】问题
解决方式二:MD5内容压缩
长链接做md5加密:比如加密成:43E08496,9E5CF455,E6D2D2B3,3407A6D2
加密串查询是否已经生成过短链接
如果已经存在,则拼接时间戳再MD5加密,插入数据库
如果不存在则把长链接、长链接加密串插入数据库
取MD5后 最后1 个 8 位字符串作为短链码
是否存在重复: 存在碰撞(重复)可能
是有损压缩算法,数据量超大情况碰撞概念越大
比如隔壁老王的女友有300多个,每再多1个,再同一天生日的概率越大,就更加复杂
解决方式三(建议使用的方式):
哈希算法:将一个元素映射成另一个元素
加密哈希,如SHA256、MD5
非加密哈希,如MurMurHash,CRC32
本节采用MurMurHash
Murmur哈希是一种非加密散列函数,适用于一般的基于散列的查找。它在2008年由Austin Appleby创建,在Github上托管,名为“SMHasher” 的测试套件。 它也存在许多变种,所有这些变种都已经被公开。该名称来自两个基本操作,乘法(MU)和旋转(R)--来自百科
是一种【非加密型】哈希函数且【随机分布】特征表现更良好
由于是非加密的哈希函数,性能会比MD5强
再很多地方都用到比如Guava、Jedis、HBase、Lucence等
数据量
MurmurHash的 32 bit 能表示的最大值近 43 亿的10进制
满足多数业务,如果接近43亿则冲突概率大
MurMurHash得到的数值是10进制,一般会转化为62进制进行缩短
例子:10进制:1813342104 转62进制:1YIB7i
常规短链码是6~8位数字+大小写字母组合
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
6 位 62 进制数可表示 568 亿个短链(62的6次方,每位都有62个可能,如果扩大位数到7位,则可以支持3万5200亿)
MurmurHash的 32 bit 满足多数业务 43亿
拼接上库-表位则可以表示更多数据(后续会涉及到分库分表的,库表位)
7位则可以到到 43亿 * 62 = 2666亿
8位则可以到到 2666亿 * 62 = 1.65万亿条数据
结合短链过期数据归档,理论上满足未来全部需求了
数据库存储
单表1千万 * 62个库 * 62表 = 384亿数据(可以满足当前业务需求)
使用Guava框里里面自带Murmur算法。先转成10进制。然后再转成62进制。
短链创建工具类封装以及使用方式
@Slf4j
public class CommonUtil {
/**
* murmurhash算法
* @param param
* @return
*/
public static long murmurHash32(String param){
long murmurHash32 = Hashing.murmur3_32().hashUnencodedChars(param).padToLong();
return murmurHash32;
}
}
import net.wnn.util.CommonUtil;
import org.springframework.stereotype.Component;
@Component
public class ShortLinkComponent {
/**
* 62个字符
*/
private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 生成短链码
* @param param
* @return
*/
public String createShortLinkCode(String param){
long murmurhash = CommonUtil.murmurHash32(param);
//进制转换
String code = encodeToBase62(murmurhash);
return code;
}
/**
* 10进制转62进制
* @param num
* @return
*/
private String encodeToBase62(long num){
// StringBuffer线程安全,StringBuilder线程不安全
StringBuffer sb = new StringBuffer();
do{
int i = (int )(num%62);
sb.append(CHARS.charAt(i));
num = num/62;
}while (num>0);
String value = sb.reverse().toString();
return value;
}
}
生成的短链码长度差不多。
为什么要用62进制转换,不是64进制?
62进制转换是因为62进制转换后只含数字+小写+大写字母
而64进制转换会含有/、+这样的符号(不符合正常URL的字符)
10进制转62进制可以缩短字符,如果我们要6位字符的话,已经有560亿个组合了是可以支持业务需求的
具体的个数也是要看业务情况的,有些短链也会加入其它特殊字符
本文转自 https://blog.csdn.net/wnn654321/article/details/122022277 ,如有侵权,请联系删除。