相信大家在生活中会收到很多短信,而这些短信都有一个特点是链接很短。这些链接背后的原理是什么呢?怎么实现的?小编今天就带你们详细了解一下

我们知道,短信有些是有字数限制的,直接放一个带满各种参数的链接,不合适,另外一点是,不想暴露参数。好处无非以下:

  • 太长的链接容易被限制长度
  • 短链接看着简洁,长链接看着容易懵
  • 安全,不想暴露参数
  • 可以统一链接转换,当然也可以实现统计点击次数等操作

那背后的原理是什么呢?怎么实现的?让你实现这样的系统,你会怎么设计呢?【来自于某鹅场面试官】

短链接的原理

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

从下图可以看出,确实链接被302重定向到新的地址上去,返回的头里面有一个字段Location就是所要重定向的地址:

短链接怎么设计的

全局发号器

肯定我们第一点想到的是压缩,像文件压缩那样,压缩之后再解压还原到原来的链接,重定向到原来的链接,但是很不幸的是,这个是行不通的,你有见过什么压缩方式能把这么长的数字直接压缩到这么短么?事实上不可能。就像是Huffman树,也只能对那种重复字符较多的字符串压缩时效率较高,像链接这种,可能带很多参数,而且各种不规则的情况都有,直接压缩算法不现实。

那https://dx.10086.cn/tzHLFw与https://gd.10086.cn/gmccapp/webpage/payPhonemoney/index.html?channel=之间的装换是怎么样的呢?前面路径不变,变化的是后面,也就是tzHLFw与gmccapp/webpage/payPhonemoney/index.html?channel=之间的转换。

实际也很简单,就是数据库里面的一条数据,一个id对应长链接(相当于全局的发号器,全局唯一的ID):

id url
1 gd.10086.cn/gmccapp/web…
这里用到的,也就是我们之前说过的分布式全局唯一ID,如果我们直接用id作为参数,貌似也可以:https://dx.10086.cn/1,访问这个链接时,去数据库查询获得真正的url,再重定向。

单机的唯一ID很简单,用原子类AtomicLong就可以,但是分布式的就不行了,简单点可以用 redis,或者数据库自增,或者可以考虑Zookeeper之类的。

id 转换策略

但是直接用递增的数字,有两个坏处:

  • 数字很大的时候,还是很长
  • 递增的数字,不安全,规律性太强了

明显我们平时看到的链接也不是数字的,一般都是大小写字母加上数字。为了缩短链接的长度,我们必须把id转换掉,比如我们的短链接由a-z,A-Z,0-9组成,相当于62进制的数字,将id转换成为62进制的数字:

public class ShortUrl {private static final String BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";public static String toBase62(long num) {StringBuilder result = new StringBuilder();do {int i = (int) (num % 62);result.append(BASE.charAt(i));num /= 62;} while (num > 0);return result.reverse().toString();}public static long toBase10(String str) {long result = 0;for (int i = 0; i < str.length(); i++) {result = result * 62 + BASE.indexOf(str.charAt(i));}return result;}public static void main(String[] args) {// tzHLFwSystem.out.println(toBase10("tzHLFw"));System.out.println(toBase62(27095455234L));}
}

id转 62位的key 或者key装换成为id都已经实现了,不过计算还是比较耗时的,不如加个字段存起来,于是数据库变成了:

id key url
27095455234 tzHLFw gd.10086.cn/gmccapp/web…

但是这样还是很容易被猜出这个id和key的对应关系,要是被遍历访问,那还是很不安全的,如果担心,可以随机将短链接的字符顺序打乱,或者在适当的位置加上一些随机生成的字符,比如第1,4,5 位是随机字符,其他位置不变,只要我们计算的时候,将它对应的关系存到数据库,我们就可以通过连接的key找到对应的url。(值得注意的是,key必须是全局唯一的,如果冲突,必须重新生成)

一般短链接都有过期时间,那么我们也必须在数据库里面加上对应的字段,访问的时候,先判断是否过期,过期则不给予重定向。

性能考虑

如果有很多短链接暴露出去了,数据库里面数据很多,这个时候可以考虑使用缓存优化,生成的时候顺便把缓存写入,然后读取的时候,走缓存即可,因为一般短链接和长链接的关系不会修改,即使修改,也是很低频的事情。

如果系统的id用完了怎么办?这种概率很小,如果真的发生,可以重用旧的已经失效的id号。

如果被人疯狂请求一些不存在的短链接怎么办?其实这就是缓存穿透,缓存穿透是指,缓存和数据库都没有的数据,被大量请求,比如订单号不可能为-1,但是用户请求了大量订单号为-1的数据,由于数据不存在,缓存就也不会存在该数据,所有的请求都会直接穿透到数据库。如果被恶意用户利用,疯狂请求不存在的数据,就会导致数据库压力过大,甚至垮掉。

针对这种情况,一般可以用布隆过滤器过滤掉不存在的数据请求,但是我们这里id本来就是递增且有序的,其实我们范围大致都是已知的,更加容易判断,超出的肯定不存在,或者请求到的时候,缓存里面放一个空对象也是没有问题的。

到此这篇关于基于Java设计一个短链接生成系统的文章就介绍到这了/

基于Java设计一个短链接生成系统相关推荐

  1. 基于java设计一个可视化中智数计算器

    Smarandache在1995年首次描述了中智学,并提出了一种重要的数学机制,称为中智集理论,用以处理模糊及其各种类型无法处理的不精确.不确定和不确定问题.NS是由真实程度(t).不确定程度(i)和 ...

  2. 如何设计一个短链服务?

    相信很多小伙伴都使用过短链服务,但如果让你实现一个短链服务,你知道怎么实现吗?其实实现短链服务并不是很难,最主要还是需要知道一些设计思路,还需要有一些基础技术知识,例如:哈希算法.全局发号器等. 短链 ...

  3. python相关毕设题目_基于java的一个有创意的web毕设题目

    基于java的一个有创意的web毕设题目 一个有创意的web毕设题目 本课题将结合基于Java Web技术的名师一对一课程预约系统,根据本课题的最终目标,在线用户注册.相关信息发布.在线咨询.预约试听 ...

  4. 如何用Java设计一个简单的窗口界面(学习中.1)

    如何用Java设计一个简单的窗口界面 一.前言 二.简单了解 1.Swing简介 2.框架(frame) 3.层次 三.步骤 1.打开eclipse,依次创建项目,包,类. 2.代码 2.1最简单的可 ...

  5. java订单类_基于Java创建一个订单类代码实例

    这篇文章主要介绍了基于Java创建一个订单类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 需求描述 定义一个类,描述订单信息 订单id 订 ...

  6. java完成一个学生信息调查程序_利用Java设计一个简单的学生信息管理程序

    利用Java设计一个简单的控制台学生信息管理程序 此程序可作为课设的参考,其中信息存储于文件中. 创建了学生类Student,用于存储学号等的信息.创建StudentFunction类,用于实现诸如学 ...

  7. 用Java设计一个通讯录,保存读者的信息。

    用Java设计一个通讯录,保存读者的信息. 一class Address package p3;import java.io.Serializable;public class Address imp ...

  8. 独立开发变现周刊(第66期): 如何把一个短链接生成工具变成一个可持续盈利的产品?...

    分享独立开发.产品变现相关内容,每周五发布. 目录 1.Padloc: 一个开源的,端到端加密的产品. 2.Spinach: 高效完成你的每日站立会议 3.Excalidraw: 虚拟白板,用于手绘图 ...

  9. java设计一个形状shape_编程定义一个图形接口 Shape, 内含2个抽象方法 get... JAVA编程题:编一个程序包含一个接口 shape(该接......

    导航:网站首页 > 编程定义一个图形接口 Shape, 内含2个抽象方法 get... JAVA编程题:编一个程序包含一个接口 shape(该接... 编程定义一个图形接口 Shape, 内含2 ...

最新文章

  1. PLSQL创建Oracle定时任务
  2. C/C++【顺序表】【初始化、赋值、打印、取值、查找、插入、删除、销毁、综合举例】
  3. RocketMQ Filtersrv
  4. 每日英语:Why Sit Up Straight?
  5. 三次握手的本质_动画讲解TCP的3次握手,4次挥手,让你一次看明白
  6. python画简单图-使用Python中的Turtle库绘制简单的图形
  7. php 学习笔记之搭建开发环境(mac版)
  8. python3的spyder安装_Python开发环境Spyder安装教程
  9. matlab各种分布计算公式,SPC常见项目的计算公式
  10. 数码照片的Photoshop清晰化处理漫谈-photoshop-Photoshop-天极Yesky
  11. c# 监听 Modern Standby 下的电源状态(Sleep mode)
  12. linux打印机测试程序,轻松了解Linux打印之CUPS软件
  13. C语言(求解一元二次方程的根)
  14. Android APP启动时出现白屏或者黑屏怎么办?
  15. 专利修改:ps换填充色
  16. 计算机图形学:向量运算(OpenGL)
  17. 【毕业设计】基于 STM32 的自动泊车系统 -智能小车 - 物联网单片机
  18. 「学科总结」 《运筹学基础》
  19. 全功能音视频互动开发平台
  20. 关于SM总线控制器驱动的安装

热门文章

  1. 赋能自动驾驶技术腾飞——海天瑞声发布『DOTS-AD』自动驾驶标注平台
  2. Another Redis使用手册
  3. java--新猿来瞅瞅==那些烦人的符号
  4. 【小猫爪】AUTOSAR学习笔记02-Communication Stack简介
  5. 电脑出现Windows Xp后就黑屏,进不了系统的解决办法
  6. 优富管家信用卡收款工具,支持还款收款
  7. NOVA温控器参数笔记(六)(G.OUT)
  8. Houdini教程:程序化岩石(1)生成高模
  9. 固态硬盘寿命计算公式
  10. 文件名后缀查看及修改