从线报群看短链接技术

(提前申明,此文只谈技术,不谈运营)

最近疫情严重,导致副业搜索量大大的增加。而在机缘巧合之下,接触到了那种所谓的线报群。就是一个群里,定时会有各种各样的优惠链接之类的。先不说质量如何,低廉的价格就很容易让人产生看一看的欲望。

从线报群看短链接技术_第1张图片

于是我百度了一下类似的情况,结果发现,这种名叫“淘宝客”的职业。在不断的研究和尝试之后,挖掘了一把更深层次的东西。

(正文开始了)

首先从上图开始吧,可以看到上图包含的两个东西,第一个是所谓的“淘口令”,第二个则是所谓的短链接。

其实这两个东西从理论上来讲,是同一个东西。我们可以起一个名字叫做映射。简单来说,就是在服务端以key-value存储一个映射关系,key代表短链接,value代表长连接。需要的时候,直接通过key获取到value的值就可以了。

举例说明:(你可以自己尝试一下,跳转位置绝对是一模一样的)

这个是长链接

https://jq.qq.com/?_wv=1027&k=cFU9YWW1

这个是生成后的短链接(具有时效性)

http://qq.cn.hn/xHS

大致流程是这样的:我复制(输入)了一个长链接,通过在线的短链接的转化后得到一个以http://qq.cn.h开头的短链接,然后我可以将该网址在互联网上进行分享和传播,其他人在访问该短网址可以进入到之前原本长网址对应的页面。

  1. 那么到底是如何才能压缩链接呢?

常见的短链接压缩算法有两种:

第一种是对 URL 进行hash运算,在得到的hash值上做进一步运算,得到一个较短的hash值。(这种方式说白了,就是给字符串进行hash加密,然后在得到hash值上再次进行运算,这样理论上得到了一个长度更短的值,但是这种情况下,URL数量不断的增加,绝对会增加冲突数量,最终导致一部分用户跳转到错误的地址上。)

第二种是通过数据库自增ID或分布式key-value系统模拟发号器进行发号压缩URL。(这种方式就比较简单了,先设置一个发号器,给每一个数据发一个号码,然后通过这个号码来映射,你说这个号码也太简单了,容易被破解?看下图,对一个数字进行进制化处理,就能满足你的条件了,如果还不行,在固定位数加上随机数字?)

从线报群看短链接技术_第2张图片

(重头戏啊)

接下里我讲一讲,我当时遇到的一些坑。

1.key-value到底应该要怎么存?

其实这里我做了两种方案,一种是redis,一种是mysql。这里的基本逻辑是,在mysql里存储对应的key-value值,然后在redis里进行缓存处理,毕竟每一个生成的短链接都是不会在更改的。

2.发号器该如何设置?

其实这个比较简单,发号器的作用主要是两个:1.保障能够每一次发送唯一的字段,这样就能保障短链直接不会再次冲突。2.保证具有一定的规律性,这样方便索引。这里推荐两种形式吧:

利用数据库的自增id:这种方式很简单,流程上讲,利用id进行64进制转换,将转换后的字段作为短链key。这样能够保证key 的唯一性,且不会冲突。这种缺点也很明显,依赖于数据库的自增,整体的效率以数据库的效率为主。(附上64进制转换代码)

/**
* 把10进制的数字转换成64进制
* 
* @param number
* @param shift
* @return
*/
private static String CompressNumber(long number) {
    char[] buf = new char[64];
    int charPos = 64;
    int radix = 1 << 6;
    long mask = radix - 1;
    do {
        buf[--charPos] = digits[(int) (number & mask)];
        number >>>= 6;
    } while (number != 0);
    return new String(buf, charPos, (64 - charPos));
}

雪花算法(没有任何两片雪花是一模一样的):雪花算法完全高可用,不依赖于数据库,而且生成数量大,每秒中能生成数百万的自增ID。而且也具有自增id,存入数据库中,索引效率高。但是这种方法依赖时间,而且长度一般为64位,虽然有一定的变种,但是短链长度仍旧很难把握。

3.并发情况下,如何提高效率。

目前高并发情况下,单一的线程很难跟得上发号问题,因此提出了2种办法。

第一种,预先发号。简单来说,每次发1000个号,放到redis里进行提前存储,然后每次需要号时候,去redis直接提取。这样就免除了数据库的效率限制。依次类推,我们可以实现1000个逻辑发号器,分别发尾号为0到999的号。每发一个号,每个发号器加1000,而不是加1。这些发号器独立工作,互不干扰即可。而且在实现上,也可以先是逻辑的,真的压力变大了,再拆分成独立的物理机器单元。1000个节点,估计对人类来说应该够用了。如果你真的还想更多,理论上也是可以的。

第二种,redis缓存。将一些常用的key-value值进行缓存,这样能够保证加载的速度。有常用的,那么就有不常用的。设计要给淘汰机制,然后把不常用的淘汰掉,剩下的就是常用的了。

 

更多信息,可以关注【计算机俱乐部】!

你可能感兴趣的:(编程中的那些坑,数据库,python,java,redis,大数据)