设计简单高效的短链系统

目录

 

引言

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 *  8String[] 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.mzph.cn/news/196847.shtml

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

相关文章

市场缺口投资者应该怎么做? 昂首资本一招就能盈利

当在市场交易分析中&#xff0c;投资者发现市场缺口或者价格缺口的时候&#xff0c; 昂首资本问各位投资者应该怎么才能抓住机会盈利一波。 其实在技术分析中的这个术语指的是&#xff1a;前一根棒线的收盘价和下一根棒线的开盘价之间有差距的情况。例如&#xff0c;当做市商将…

【SpringBoot系列】SpringBoot时间字段格式化

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Allegro无法模块复用的解决办法

Allegro无法模块复用的解决办法 在用Allegro做PCB设计的时候,模块复用是使用的比较频繁的功能,对于有相同模块的单板,可以节省大量的时间。 模块复用的功能不细说,具体参考以前的文章。 有时会遇到模块复用的时候出现如下报错 无法匹配,有时如果因为Device而无法复用,就…

python提取通话记录中的时间信息

您需要安装适合中文的SpaCy模型。您可以通过运行 pip install spacypython -m spacy download zh_core_web_sm来安装和下载所需的模型。 import spacy# 加载中文模型 nlp spacy.load(zh_core_web_sm)# 示例电话记录文本 text """ Agent: 今天我们解决一下这…

Linux CentOS7 安装Docker

CentOS7安装Docker&#xff1a; Docker简介 Docker是一个开源的容器化平台&#xff0c;可帮助开发者轻松地创建、部署和运行应用程序。Docker使开发人员能够在一个独立的容器中打包应用程序及其依赖项&#xff0c;这样他们就可以轻松地将应用程序移植到任何其他环境中。Docke…

基础堆溢出原理与DWORD SHOOT实现

堆介绍 堆的数据结构与管理策略 程序员在使用堆时只需要做三件事情&#xff1a;申请一定大小的内存&#xff0c;使用内存&#xff0c;释放内存。 对于堆管理系统来说&#xff0c;响应程序的内存使用申请就意味着要在"杂乱"的堆区中"辨别"出哪些内存是正在…

Python实现交易策略评价指标-夏普比率

1.夏普比率的定义 在投资的过程中&#xff0c;仅关注策略的收益率是不够的&#xff0c;同时还需要关注承受的风险&#xff0c;也就是收益风险比。 夏普比率正是这样一个指标&#xff0c;它表示承担单位的风险会产生多少超额收益。用数学公式描述就是&#xff1a; S h a r p R…

【算法每日一练]-图论(保姆级教程 篇6(图上dp))#最大食物链 #游走

目录 题目&#xff1a;最大食物链 解法一&#xff1a; 解法二&#xff1a; 记忆化 题目&#xff1a;游走 思路&#xff1a; 题目&#xff1a;最大食物链 解法一&#xff1a; 我们标记f[i]是被f[x]捕食的点对应的类食物链数 不难得出&#xff1a; f[x]∑(f[i]) 首先从生…

206 反转链表

解题思路可以有两种方法&#xff1a;递归 or 迭代。 \qquad 迭代&#xff1a;通过使用for循环遍历&#xff0c;完成目标。方法直观&#xff0c;容易理解。 \qquad 递归&#xff1a;通过函数调用其自身&#xff0c;完成目标。递归最复杂、最重要的部分就是递归函数的构建&#…

【数据结构】——栈|队列(基本功能)

目录 栈 基本概念 栈的常见基本操作 栈的存储 ✌栈的基本操作实现 栈的构建 栈的初始化 入栈 打印栈 出栈 获取栈顶元素 获取栈的有效元素个数 判断栈是否为空 销毁栈 队列 基本概念 队列的常见基本操作 ✌队列的基本操作实现 队列的构建 初始化 入队列 出…

Spring Security 6.x 系列(9)—— 基于过滤器链的源码分析(二)

一、前言 在本系列文章&#xff1a; Spring Security 6.x 系列&#xff08;4&#xff09;—— 基于过滤器链的源码分析&#xff08;一&#xff09;中着重分析了Spring Security在Spring Boot 的自动配置、 DefaultSecurityFilterChain 的构造流程、FilterChainProxy 的构造流…

详解原生Spring当中的事务

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

Spring Security 6.x 系列(8)—— 源码分析之配置器SecurityConfigurer接口及其分支实现

一、前言 本章主要内容是关于配置器的接口架构设计&#xff0c;任意找一个配置器一直往上找&#xff0c;就会找到配置器的顶级接口&#xff1a;SecurityConfigurer。 查看SecurityConfigurer接口的实现类情况&#xff1a; 在 AbstractHttpConfigurer 抽象类的下面可以看到所有…

idea类和方法模版

类模版 修改目标位置 class #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#end #parse("File Header.java")/*** ${Description}* author whc ${YEAR}/${MONTH}/${DAY}* version v1.0 */public class ${NAME} { }inte…

【网络安全】虚假IP地址攻击如何防范?

在当今的网络时代&#xff0c;虚假IP地址攻击已成为一种新型的网络攻击方式&#xff0c;给网络安全带来了极大的威胁。那么&#xff0c;什么是虚假IP地址攻击&#xff1f;又如何进行溯源和防范呢&#xff1f;本文将为您揭开这一神秘面纱。 一、虚假IP地址攻击概述 虚假IP地址攻…

[python]离线加载fetch_20newsgroups数据集

首先手动下载这个数据包 http://qwone.com/~jason/20Newsgroups/20news-bydate.tar.gz 下载这个文件后和脚本放一起就行&#xff0c;然后 打开twenty_newsgroups.py文件&#xff08;在fetch_20newsgroups函数名上&#xff0c;右键转到定义即可找到&#xff09; 之后运行代码即…

羊大师教你如何有效应对冬季流感,保护自己与家人

羊大师教你如何有效应对冬季流感&#xff0c;保护自己与家人 随着冬季的临近&#xff0c;流感病毒将再次蔓延。如何预防冬季流感来袭&#xff0c;成为了许多人关注的话题。幸运的是&#xff0c;我们可以采取一系列的预防措施来保护自己和家人&#xff0c;避免被流感侵袭。下面…

【Altium designer 20】

Altium designer 20 1. Altium designer 201.1 原理图库1.1.1 上划岗 在字母前面加\在加字母1.1.2 自定义快捷键1.1.3 对齐1.1.4 在原有的电路图中使用封装1.1.5 利用excel创建IC类元件库1.1.6 现有原理图库分类以及调用1.1.7 现有原理图库中自动生成原理图库 1.2 绘制原理图1.…

【初阶解法-数据结构】包含min函数的栈(代码+图示)

【数据结构】刷题-包含min函数的栈(代码图示)-初阶解法 文章目录 【数据结构】刷题-包含min函数的栈(代码图示)-初阶解法题目提炼题目要求分析题目总结思路代码时间/空间复杂度进阶版 题目 定义栈的数据结构&#xff0c;请在该类型中实现一个能够得到栈中所含最小元素的 min 函…

Ubuntu22.04 交叉编译mp4V2 for Rv1106

一、配置工具链环境 sudo vim ~/.bashrc在文件最后添加 export PATH$PATH:/opt/arm-rockchip830-linux-uclibcgnueabihf/bin 保存&#xff0c;重启机器 二、下载mp4v2 下载路径&#xff1a;MP4v2 | mp4v2 三、修改CMakeLists.txt 四、执行编译 mkdir build cd buildcmak…