设计简单高效的短链系统

news2024/9/30 5:25:49

目录

 

引言

1. 短链系统的原理

1.1 长链接生成短码

1.2 短码映射到长链接

1.3 短码重定向

1.4 过期短 URL 清理

2. 设计与实现

2.1 数据存储

2.2 短码生成

2.3 接口设计

2.4 安全性考虑

2.5 访问性能优化


引言

        在当今数字化时代,人们对信息的分享需求不断增长,而长串复杂的URL链接却显得不够便捷和美观。为了解决这一问题,短链系统应运而生。本文将探讨设计一个简单高效的短链系统的原理与实现。

        例如在手机上会收到类似的信息,最后会被转到另外一个url,比如下面的链接会被定向到 https://page.xiaojukeji.com/active/ddpage_0IM6bugY.html?sojumpparam=gR2+gSMzQEIjGhpfDLdIwy2xcBkmZNG08Y36D09Ti90UwuMj1EccLugZQSvIuSVS&sampleId=t9dT0cXFt6O7JGe3BFOqDQ==&issueId=4124142163&origin=flicka&traceId=null

 链接上,并且这种链接有时效性,过一段时间会失效。

短链系统的简单执行流程 

 

1. 短链系统的原理

        短链系统的核心原理是通过将长URL映射到短的、容易记忆的字符串上,从而实现对原始链接的缩短。其基本流程如下:

1.1 长链接生成短码

        当用户输入或提交长URL时,系统首先会生成一个唯一的短码,可以是数字、字母组合,或者是更复杂的自定义规则。这一过程通常涉及到一种哈希算法,确保每个长链接对应一个唯一的短码。

1.2 短码映射到长链接

        生成短码后,系统需要建立一个映射关系,将短码与原始的长URL关联起来。这可以通过数据库或者缓存系统来实现,以便快速地检索和获取原链接。

1.3 短码重定向

        当用户访问短链接时,系统通过短码查找对应的原链接,并进行重定向,将用户引导至原始的长链接地址。

1.4 过期短 URL 清理

        过期短 URL 清理服务器定时启动一次,将已经超过有效期的 URL 数据删除。

2. 设计与实现

2.1 数据存储

        为了实现短码到长链接的映射,需要一个高效的数据存储系统。常见的选择包括关系型数据库(如MySQL)、NoSQL数据库(如Redis)或者分布式存储系统(如HDFS)。数据库的设计应考虑性能、可扩展性和数据一致性。

2.2 短码生成

        短码的生成可以使用基于哈希的算法,确保唯一性。另外,可以考虑使用自定义规则,比如将长码进行Base62编码,生成短码。

        将长 URL 利用 MD5 或者 SHA256 等单项散列算法,进行 Hash 计算,得到128bit 或者 256bit 的 Hash 值。然后对该 Hash 值进行 Base64 编码,得到 22个或者 43 个 Base64 字符,再截取前面的 6 个字符,就得到短 URL 了。

        但是这样得到的短 URL,可能会发生 Hash 冲突,即不同的长 URL,计算得到的短 URL 是相同的(MD5 或者 SHA256 计算得到的 Hash 值几乎不会冲突,但是 Base64 编码后再截断的 6 个字符有可能会冲突)。所以在生成的时候,需要先校验该短 URL 是否已经映射为其他的长 URL,如果是,那么需要重新计算。
        
     我们的思路:
       1)将长网址md5生成32位签名串,分为4段, 每段8个字节;
       2)对这四段循环处理, 取8个字节, 将他看成16进制串与0x3fffffff(30位1)与操作, 即超过30位的忽略处理;
       3)这30位分成6段, 每5位的数字作为字母表的索引取得特定字符, 依次进行获得6位字符串;
       4)总的md5串可以获得4个6位串; 取里面的任意一个就可作为这个长url的短url地址;

 代码

 public static String[] shortUrl(String url) {
        // 对传入网址进行 MD5 加密
        String sMD5EncryptResult = DigestUtils.md5Hex(url);
        System.out.println("---------------sMD5EncryptResult: "+sMD5EncryptResult);
        System.out.println();
        //md5处理后是32位
        String hex = sMD5EncryptResult;
        //切割为4组,每组8个字符, 32 = 4 *  8
        String[] resUrl = new String[4];

        for (int i = 0; i < 4; i++) {
             //取出8位字符串,md5 32位,按照8位一组字符,被切割为4组
            String sTempSubString = hex.substring(i * 8, i * 8 + 8);
            System.out.println("---------------sTempSubString: "+sTempSubString);
           //System.out.println("-sTempSubString作为16进制的表示"+Long.parseLong(sTempSubString, 16));

       //把加密字符按照8位一组16进制与 0x3FFFFFFF 进行位与运算
            // 这里需要使用 long 型来转换,因为 Inteper .parseInt() 只能处理 31 位 , 首位为符号位 , 如果不用 long ,则会越界
            long lHexLong = 0x3FFFFFFF & Long.parseLong(sTempSubString, 16);
            System.out.println("---------lHexLong: "+lHexLong);

            String outChars = "";
            for (int j = 0; j < 6; j++) {
                //0x0000003D它的10进制是61,61代表最上面定义的chars数组长度62的0到61的坐标。
                //0x0000003D & lHexLong进行位与运算,就是格式化为6位,即保证了index绝对是61以内的值
                long index = 0x0000003D & lHexLong;
                System.out.println("----------index: "+index);
                // 按照下标index把从chars数组取得的字符逐个相加
                outChars += chars[(int) index];
                //每次循环按位移5位,因为30位的二进制,分6次循环,即每次右移5位
                lHexLong = lHexLong >> 5;
            }
            // 把字符串存入对应索引的输出数组,会产生一组6位字符串
            resUrl[i] = outChars;
        }
        return resUrl;
    }

2.3 接口设计

设计清晰简单的API接口,包括长链转短链、短链还原成长链等功能。使用RESTful风格可以使接口易于理解和使用。

我们需要两个接口

  • 一个是生成短链接接口

这个接口就是生成短链接,并存放在缓存数据库中。

  • 另一个是重定向到原始的URL

这个接口知识点是重定向,需http状态码的知识

  • 301:永久重定向,浏览器会缓存,自动重定向到新的地址
  • 302:临时重定向,客户端还是会继续使用旧的URL

整个跳转的流程:

  • 1.用户访问短链接,请求到达服务器
  • 2.服务器将短链接装换成为长链接,然后给浏览器返回重定向的状态码301/302
    • 301永久重定向会导致浏览器缓存重定向地址,短链接系统统计访问次数会不正确
    • 302临时重定向可以解决次数不准的问题,但是每次都会到短链接系统转换,服务器压力会变大。
  • 3.浏览器拿到重定向的状态码,以及真正需要访问的地址,重定向到真正的长链接上。

2.4 安全性考虑

        考虑到潜在的滥用和安全威胁,需要实施一些安全机制,例如限制短链接的有效期、监控访问频率等。

        比如如果我们使用redis来存储短链接,我们再放入redis中,同时设置好过期时间。如果使用mysql或者分布式存储HDFS来存储时,可以使用定时任务来清理过期的短链接。

2.5 访问性能优化

        通过合理的缓存机制和负载均衡,保证系统在高并发情况下依然能够快速响应用户请求。

        使用redis存储短链接的数据结构可以使用hash结构来存储短链接到长链接的映射。

        使用布隆过滤器可以防止被人疯狂请求一些不存在的短链接,导致数据库压力过大,甚至垮掉。

        另外在生成短链接时,我们可以使用预生成的短URL,预生成短 URL 的算法可以采用随机数来实现,6 个字符,每个字符都用随机数产生(用0~63 的随机数产生一个 Base64 编码字符)。为了避免随机数产生的短 URL 冲突,需要在预生成的时候检查该 URL 是否已经存在(用布隆过滤器检查)。因为预生成短URL是离线的,所以这时不会有性能方面的问题。并且预生成短 URL可以存储在文件系统中供我们使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1283533.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

你敢挑战吗?网易面试题,用不规则的3升和5升杯子如何在无限水中得到4升水?

嗨&#xff0c;亲爱的小米粉丝们&#xff01;今天小米要和大家一起挑战一道网易产品面试题&#xff1a;3升的杯子一个&#xff0c;5升的杯子一个&#xff0c;杯子形状不规则&#xff0c;水却是无限的&#xff0c;我们要怎么得到4升的水呢&#xff1f;别急&#xff0c;小米来给你…

大文件分片上传、分片进度以及整体进度、断点续传【前端原生、后端 Koa、Node 原生】(一)

分片&#xff08;500MB&#xff09;进度效果展示 效果展示&#xff0c;一个分片是 500MB 的 分片&#xff08;10MB&#xff09;进度效果展示 大文件分片上传效果展示 前端 思路 前端的思路&#xff1a;将大文件切分成多个小文件&#xff0c;然后并发给后端。 页面构建 先在页…

百望云供应链协同解决方案入选北大创新评论产业研究案例库

11月28日-29日&#xff0c;百望云受邀出席《北大创新评论》2023 Inno China 中国产业创新大会&#xff0c;从战略构建、生态塑造、科技创新等议题出发&#xff0c;与学术专家、产业专家、企业代表共赴盛会&#xff0c;思享汇聚。会上&#xff0c;《北大创新评论产业研究案例库&…

提升--21---JMM(Java内存模型)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 JMM--Java Memory ModelJMM 定义JMM规则&#xff1a;线程间通信的步骤&#xff1a; JMM的三大特性&#xff1a;原子性&#xff08;Atomicity&#xff09;可见性&…

uniapp是否可以用vant等移动端UI库、使用步骤以及需要注意的问题

文章目录 使用vant步骤使用中遇到的问题在浏览器中的运行效果综上&#xff0c;不建议uniapp项目使用vant。 使用vant步骤 首先vant可以兼容uniapp&#xff0c;直接用vant版就好。微信小程序专用版本是&#xff1a;vant-weapp。 基本使用步骤&#xff1a; 1、安装 # 安装 Va…

Django创建基本的app应用并配置URL路径-成功运行服务

开发环境&#xff1a;Pycharm2021 Win11 首先创建虚拟环境: 可参考&#xff1a; Pycharm开发环境下创建python运行的虚拟环境&#xff08;自动执行安装依赖包&#xff09;_pycharm自动下载依赖包_heda3的博客-CSDN博客 1、安装 Django 在虚拟环境下安装pip install django …

任意密码重置+CRRF

一、XSS漏洞 在商城的搜索处&#xff0c;输入标准语句的传参直接就可以弹窗 二、逻辑漏洞-用户枚举 在用户注册界面&#xff0c;点击发送验证码&#xff0c;然后用BURP发包 更改手机号传参&#xff0c;这里手机号传参没有进行加密&#xff0c;直接用手机号的位置进行爆破 正确的…

根文件系统lib库添加与初步测试

一. 简介 我们在编译 busybox源码时&#xff0c;选择的是动态编译&#xff0c;所以&#xff0c;制作生成的 根文件系统中/bin或 /sbin目录下软件运行时会调用到一些库文件的。库文件就是交叉编译器的库文件。 前面我们编译 busybox源码时&#xff0c;选择动态编译&#xff0…

JavaEE之多线程编程(一):基础篇

文章目录 一、关于操作系统一、认识进程 process二、认识线程三、进程和线程的区别&#xff08;重点&#xff01;&#xff09;四、Java的线程和操作系统线程的关系五、第一个多线程编程 一、关于操作系统 【操作系统】 驱动程序&#xff1a; 如&#xff1a;我们知道JDBC的驱动程…

【接口测试】POST请求提交数据的三种方式及Postman实现

1. 什么是POST请求&#xff1f; POST请求是HTPP协议中一种常用的请求方法&#xff0c;它的使用场景是向客户端向服务器提交数据&#xff0c;比如登录、注册、添加等场景。另一种常用的请求方法是GET&#xff0c;它的使用场景是向服务器获取数据。 2. POST请求提交数据的常见编…

笔记-模拟角频率和数字角频率的关系理解

先建议阅读前人此文&#xff08;点击这里&#xff09;&#xff0c;有助于理解。 模拟频率&#xff1a;f 模拟角频率&#xff1a;Ω 数字角频率&#xff1a;ω 其中&#xff1a;在模拟信号中Ω 2πf 正弦波表示&#xff1a;sin(2πft) sin(Ωt) 数字信号就是离散的&#xff…

Facebook推广工具功能科普!

随着社交媒体的普及&#xff0c;Facebook已经成为全球使用最广泛的社交平台之一&#xff0c;对于广大营销人员来说&#xff0c;利用Facebook推广工具进行营销已经成为不可或缺的一部分。 那么&#xff0c;这些推广工具到底有哪些功能呢?本文将为您揭秘Facebook推广工具的强大…

Pytest 使用及调用方法

使用python -m pytest调用pytest 2.0版本新增 你可以在命令行中通过Python编译器来调用Pytest执行测试: python -m pytest [...] 通过python调用会将当前目录也添加到sys.path中,除此之外,这几乎等同于命令行直接调用pytest [...]。 可能出现的执行退出code 执行pytest可能…

公众号50个数量怎么操作?

一般可以申请多少个公众号&#xff1f;公众号申请限额在过去几年内的经历了很多变化。对公众号申请限额进行调整是出于多种原因&#xff0c;确保公众号内容的质量和合规性。企业公众号的申请数量从50个到5个最后到2个&#xff0c;对于新媒体公司来说&#xff0c;这导致做不了公…

移动端APP自动化测试框架-UiAutomator2基础

很早以前&#xff0c;我用uiautomatorjava实践过Android APP自动化测试&#xff0c;不过今天要提的不是uiautomator&#xff0c;而是uiautomator2。听起来uiautomator2像是uiautomator的升级版&#xff0c;但是这两款框架仅仅是名字上比较相似&#xff0c;实际上没有任何关联。…

蓝桥杯物联网竞赛_STM32L071_10_温度传感器扩展模块

原理图&#xff1a; 温度传感器原理图&#xff1a; 其中芯片可以通过SCL和SDA引脚通过I2C通信向温度传感器指定地址获取温度的模拟量 再利用公式将模拟量转换成相应温度即可 实验板接口原理图&#xff1a; 模拟量转相应温度公式&#xff1a; CubMx配置&#xff1a; Keil配置&…

深度学习算法:探索人工智能的前沿

目录 引言 第一部分&#xff1a;深度学习的基础 1.1 什么是深度学习&#xff1f; 1.2 神经网络的演化 第二部分&#xff1a;深度学习的关键技术 2.1 卷积神经网络&#xff08;CNN&#xff09; 2.2 循环神经网络&#xff08;RNN&#xff09; 2.3 长短时记忆网络&#xf…

Vue3集成ThreeJS实现3D效果,threejs+Vite+Vue3+TypeScript 实战课程【一篇文章精通系列】

Vue3集成ThreeJS实现3D效果&#xff0c;threejsViteVue3TypeScript 实战课程【一篇文章精通系列】 项目简介一、项目初始化1、添加一些依赖项 二、创建3D【基础搭建】1、绘制板子&#xff0c;立方体&#xff0c;球体2、材质和光照3、材质和光照和动画4、性能监控5、交互控制6、…

Liunx系统使用超详细(三)

本篇内容开始逐渐描述有关liunx的各种命令的使用方法&#xff01; 目录 一、目录和文件区别 1.1目录&#xff1a; 1.2文件&#xff1a; 1.3总结&#xff1a; 二、Linux命令的写法 三、linux命令清屏 四、pwd命令 五、ls命令 5.1 ls&#xff1a; 5.2 ls -l&#xff1a…

【C++】异常处理 ⑧ ( 标准异常类 | 标准异常类继承结构 | 常用的标准异常类 | 自定义异常类继承 std::exception 基类 )

文章目录 一、抛出 / 捕获 多个类型异常对象1、标准异常类2、标准异常类继承结构3、常用的标准异常类 二、自定义异常类继承 std::exception 基类1、自定义异常类继承 std::exception 基类2、完整代码示例 - 自定义异常类继承 std::exception 基类 一、抛出 / 捕获 多个类型异常…