# 技术杂谈

短链生成方案初级入门

2023-02-10 17:42:06
16

目录

1.问题一:长链的关系和短链的关系是一对一还是一对多?

2.问题二:前端访问短链是如何跳转到对应的页面的?

3.问题三:短链码如何是如何生成的

  为什么要用62进制转换,不是64进制?


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 ,如有侵权,请联系删除。

最后编辑于 2024-10-31 14:05:47