最通俗易懂的短链接原理讲解

看业务代码的时候,有些逻辑用到了短链接服务,感觉还蛮有意思的,这里简单的记录一下。

这种营销短信大家应该都收到过,短信有最大字符限制,而且为了更好的观感体验,短信里的链接一般都很短。现成的短链接生成服务也比较多,比如新浪百度等,谷歌之前也有短链接服务,号称是最快的,但是在 2018 年关闭了。

一、短链接原理

我们点击短链接会发起一个 GET 方式的 HTTP 请求,当请求到对应的 API 后,会解析短链接里的标识获取到对应的长链接,然后重定向到长链接,这样整个流程就结束了。

比如我用新浪的短链接服务为 https://www.google.com/ 生成了一个短链接:http://dwz.date/evn,下面是请求短链接时对应的 HTTP 信息:

二、短链接生成算法

短链接标识一般是 [0-9, a-z, A-Z] 随机组合而成的字符串,字符一共有 62 个,因此短链接标识可以用 62 进制的字符串表示。

首先维护一个自增的 ID,当生成短链接时,将 10 进制的自增 ID 转换成 62 进制字符串,这个字符串就可以唯一标识一个长链接。由于 ID 是自增的,对应的 62 进制字符串是不同的,这样就不会出现一个短链接对应多个长链接的问题,62 个字符排列组合,可以保证短链接是用不完的,就算仅限于 6 位长度标识的短链接,也有 558 亿多种情况,这种算法在网上被称为自增序列算法。

维护自增 ID 主要有以下几种方式:

  1. 数据库主键自增
  2. redis 自增
  3. 分布式自增主键 ID(雪花算法,存在 ID 浪费)

下面是 62 进制的 encode 与 decode 方法,来自 Base62

    private static String base62(Long b10) {
        StringBuilder ret = new StringBuilder();
        while (b10 > 0) {
            ret.insert(0, characters.charAt((int) (b10 % 62)));
            b10 /= 62;
        }
        return ret.toString();
    }

    private static long decodeBase62(String b62) {
        long ret = 0;
        b62 = new StringBuffer(b62).reverse().toString();
        long count = 1;
        for (char character : b62.toCharArray()) {
            ret += characters.indexOf(character) * count;
            count *= 62;
        }
        return ret;
    }

三、一些细节

  1. 自增序列算法也存在一定的缺点,当自增主键很大时,生成的 62 进制字符串会变长,以 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 顺序的 62 进制为例,当主键大于 56800235583 时,会生成 7 位长度的 62 进制字符串。这个问题可以通过控制自增主键的增长速度来解决,而且要避免主键浪费。
  2. 62 进制的顺序并不一定严格按照 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 的顺序来表示,这个顺序可以是打乱的,这样生成的短链接标识更随机不易被破解。
  3. 长链接与短链接是否需要一对多关系,同一个长链接使用自增主键 ID 算法生成的短链接是不同的,因为自增主键 ID 不同,生成的 62 进制字符串自然也不同。如果我们有一个长链接唯一对应一个短链接需求,可以将长链接进行 md5 加密,将加密后的 md5 值存储在 DB 中,每次生成短链接前都根据长链接 md5 值查询 DB,如果存在,则直接返回短链接,当然也可以使用其他方式维护这种关系。
  4. 跳转用 301 还是 302,301 永久重定向,302 是临时重定向。短地址一经生成就不会变化,所以用 301 是符合 http 语义的。同时对服务器压力也会有一定减少。
    但是如果使用了 301,我们就无法统计到短地址被点击的次数了。而这个点击次数是一个非常有意思的大数据分析数据源。能够分析出的东西非常非常多。所以选择 302 虽然会增加服务器压力,但是我想是一个更好的选择。from 短 URL 系统是怎么设计的? by iammutex
  5. 如果短链接请求频繁,可以借助 redis 做对应的缓存优化。

PS:做一次标题党,师承 SCDN 官方😂

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java-Base64算法_创新_防止表单重复提交 JAVA企业级基础课题(HashMap那些事) 企业架构师必备技能(JAVA核心技术反射) JavaWeb之基础(手写实现Tomcat服务器) java多线程编程 纯手写实现SpringIOC实现过程 JEE企业级开发(企业级项目开发权威指南) 网络爬虫之JAVA正则表达式 手写springMVC框架 老司机带你透析springMVC内部实现方式 打造高效代码结构(java性能优化) 新版本通俗易懂_观察者模式递进时讲解 ibatis连接数据库 高并发之单(多)生产者消费者线程 高并发复用数据库链接技术详解之数据库连接池 类加载器的高级特性(自定义类加器实现加密解密) iBATIS开源主流框架(实现半自动化hibernate) 企业实用技能之详解(眼睛横纹模式验证码防止恶意登陆) 动态页面的静态化处理 图片上传技术 在springMVC中实现原始的Excel文件下载方式 企业级分布式缓存技术之(redis详解) 企业高并发基石(Tomcat服务器性能优化) spring事务处理 课程文档 高并发之基础数据MySql调优 mongodb 三级联动课程资料 应用架构之灵魂设计模式 应用架构之魂设计模式实战演练应用架构之魂设计模式实战演练 揭开springAOP神秘面纱(动态代理) Mysql性能优化之索引优化 写实现Tomcat服务器 移动后台端框架设计 公司级框架原理解析 解密公司内部框架开发(打造属于自己的专属框架) 手写Tomca之深度解析动态资源请求原理 深度解析springMVC实现原理(手写springMVC框架) Java验证码 正则黑名单爬虫系统 深入数据库连接池内部运转原理 分布式服务下的交易一致 企业必备技能之面向服务编程Web-Service详解 分布式服务下的交易一致性原理及解决 分布式服务框架(dubbo+zookpeer) WEB高级前后台分离思维-懒加载无限级树形菜单 动态页面的静态化处理 大并发展示优化,动态页面的静态化 深入理解JDK动态代理本质 企业级高并发缓存解决方案 性能优化之Oracle语句优化雾区 前后台数据验证架构源码级解析 session跨域共享 JAVANIO原理详解 高并发数据库(Mysql数据库性能优化) 软件质量管控 企业常用框架springMVC基于注解+xml配置方式实现链接 WEB服务器优化之Tomcat7性能调优 JVM概述 Java开发技术之(项目工程的日志管理) 数据库连接池原理详解 Java企业级框架之核心技术(反射) Java-Base64算法(创新_防止表单重复提交) 揭开springAOP神秘面纱之动态代理 网络爬虫之JAVA正则表达式
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程简介 从零开始讲解大数据业务及数据采集和迁移需求,以案例驱动的方式讲解基于Sqoop构建高性能的分布式数据迁移和同步平台。 课程亮点 1,知识体系完备,从小白到大神各阶段读者均能学有所获。 2,生动形象,化繁为简,讲解通俗易懂。 3,结合工作实践及分析应用,培养解决实际问题的能力。 4,每一块知识点, 都有配套案例, 学习不再迷茫。 适用人群 1、对大数据感兴趣的在校生及应届毕业生。 2、对目前职业有进一步提升要求,希望从事大数据行业高薪工作的在职人员。 3、对大数据行业感兴趣的相关人员。 课程内容 第一章:企业数据迁移需求及解决方案 1.企业级数据迁移及同步需求 2.Sqoop的设计思想 3.Sqoop与Hadoop的关系 4.Sqoop的分布式实现原理 5.Sqoop的企业级版本选型 6.Sqoop的部署安装及配置 第二章:Sqoop数据导入实战开发 1.Sqoop导入开发参数详解 2.数据导入分布式文件系统HDFS 3.数据导入数据仓库Hive 4.基于复杂条件实现数据导入 5.基于订单案例实现Increment增量同步数据 6.基于订单案例实现lastModified增量同步导入数据 7.数据导入原理详解 第三章:Sqoop数据导出实战开发 1.Sqoop导出开发参数详解 2.基于MySQL实现数据导出 3.基于案例实现updateonly增量同步导出 4.基于案例实现allowinsert增量同步导出 5.数据导出原理详解 第四章:Sqoop企业级任务管理 1.企业级数据管理业务 2.Sqoop Job命令参数详解 3.基于订单案例实现Sqoop Job实战开发 4.Sqoop Job 任务管理
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程简介 从零开始讲解大数据分布式计算的发展及Impala的应用场景,对比Hive、MapReduce、Spark等类似框架讲解内存式计算原理,基于Impala构建高性能交互式SQL分析平台 课程亮点 1,知识体系完备,从小白到大神各阶段读者均能学有所获。 2,生动形象,化繁为简,讲解通俗易懂。 3,结合工作实践及分析应用,培养解决实际问题的能力。 4,每一块知识点, 都有配套案例, 学习不再迷茫。 适用人群 1、对大数据感兴趣的在校生及应届毕业生。 2、对目前职业有进一步提升要求,希望从事大数据行业高薪工作的在职人员。 3、对大数据行业感兴趣的相关人员。 课程内容 第一章:内存式计算发展 1.分布式计算的发展 2.大数据分布式计算分类 3.Impala内存式计算诞生 第二章:Impala原理初探 1.Impala的设计思想 2.Impala与Hive之间的联系 3.Impala的分布式架构详解 4.Impala角色概念详解 第三章:基于Cloudera镜像部署分布式Impala 1.基于CDH5.14构建本地Yum镜像 2.企业级分布式Impala部署 3.企业级配置与Hadoop集成 4.企业级配置与Hive集成 5.主从架构及元数据服务管理 第四章:Impala企业实战开发案例 1.基于企业案例实现Impala集群管理 2.Impala最全SQL语法详解 3.实战开发Impala数据库与表管理 4.基于分析案例实现Impala数据管理 5.Impala与应用系统集成JDBC 第五章:Impala原理深入 1.Impala各角色功能详解 2.Impala任务提交原理 3.Impala元数据同步原理
手把手视频详细讲解项目开发全过程,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程简介 从零开始讲解大数据列式存储NoSQL数据库Kudu,基于Kudu构建高性能随机读写访问的数据存储系统,原理从入门到深入,搞定面试 课程亮点 1,知识体系完备,从小白到大神各阶段读者均能学有所获。 2,生动形象,化繁为简,讲解通俗易懂。 3,结合工作实践及分析应用,培养解决实际问题的能力。 4,每一块知识点, 都有配套案例, 学习不再迷茫。 适用人群 1、对大数据感兴趣的在校生及应届毕业生。 2、对目前职业有进一步提升要求,希望从事大数据行业高薪工作的在职人员。 3、对大数据行业感兴趣的相关人员。 课程内容 第一章:NoSQL数据库应用 1.NoSQL的应用及其发展 2.常见NoSQL数据库及应用场景 第二章:Kudu原理详解 1.Kudu的介绍及其发展 2.Kudu的设计思想 3.Kudu与Hbase对比 4.Kudu的分布式架构模型 5.Kudu中的特殊概念 6.Kudu的存储模型 第三章:Kudu的分布式环境部署 1.Cloudera Yum镜像配置 2.企业级分布式集群规划 3.企业级分布式计算安装 4.企业级集群管理配置 5.Kudu分布式集群管理 第四章:Kudu开发实战 1.Kudu Java API开发实战 2.Kudu分区器策略详解 3.Spark集成Kudu实战案例 4.Impala集成Kudu实战案例 第五章:Kudu原理深入搞定面试题 1.Table与Schema原理分析 2.Kudu数据模型分析 3.Kudu数据存储流程 4.Kudu数据读取流程 5.Kudu数据更新流程
生成链接可以通过以下几种方式实现: 1. 使用第三方链接服务API,比如新浪微博、腾讯、百度等都有提供链接服务的API,可以通过调用API将长链接转换为链接。 2. 自己实现链接生成算法,将长链接转换为一串字符串,比如将长链接的MD5值作为链接的标识符,再将标识符与链接域名组合成链接。需要注意的是,自己实现的链接算法需要保证生成的链接是唯一的,且不易被猜测。 以下是一个使用自己实现的算法生成链接的Java示例代码: ```java public class ShortUrlGenerator { private static final String BASE62 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; private static final int BASE = 62; public static String generate(String longUrl) { String md5 = DigestUtils.md5Hex(longUrl); String hex = md5.substring(0, 8); long hexLong = Long.parseLong(hex, 16); StringBuilder sb = new StringBuilder(); while (hexLong > 0) { int remainder = (int) (hexLong % BASE); sb.append(BASE62.charAt(remainder)); hexLong /= BASE; } return sb.toString(); } } ``` 使用方法如下: ```java String longUrl = "http://www.example.com/long/url"; String shortUrl = ShortUrlGenerator.generate(longUrl); System.out.println("Short URL: " + shortUrl); ``` 该算法使用MD5将长链接转换为一串16进制字符串,再将该字符串转换为10进制数字,最后将10进制数字转换为62进制字符串作为链接的标识符。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值