短 URL 服务,怎么设计与实现?
程序员的成长之路
共 4654字,需浏览 10分钟
· 2020-08-28
阅读本文大概需要 5 分钟。
前言
短. 短信和许多平台(微博)有字数限制,太长的链接加进去都没有办法写正文了.
好看. 比起一大堆不知所以的参数,短链接更加简洁友好.
方便做一些统计.你点了链接会有人记录然后分析的.
安全. 不暴露访问参数.
短URL基础原理
有一个服务,将要发送给你的长URL对应到一个短URL上.例如
www.baidu.com -> www.t.cn/1
把短url拼接到短信等的内容上发送.
用户点击短URL,浏览器用301/302进行重定向,访问到对应的长URL.
展示对应的内容.
服务设计
对应关系如何存储?
如何保证长短链接一一对应?
短URL的存储
高并发
分布式
实现
package util;
import redis.clients.jedis.Jedis;
/**
* Created by pfliu on 2019/06/23.
*/
publicclass ShortUrlUtil {
privatestaticfinal String SHORT_URL_KEY = "SHORT_URL_KEY";
privatestaticfinal String LOCALHOST = "http://localhost:4444/";
privatestaticfinal String SHORT_LONG_PREFIX = "short_long_prefix_";
privatestaticfinal String CACHE_KEY_PREFIX = "cache_key_prefix_";
privatestaticfinalint CACHE_SECONDS = 1 * 60 * 60;
privatefinal String redisConfig;
privatefinal Jedis jedis;
public ShortUrlUtil(String redisConfig) {
this.redisConfig = redisConfig;
this.jedis = new Jedis(this.redisConfig);
}
public String getShortUrl(String longUrl, Decimal decimal) {
// 查询缓存
String cache = jedis.get(CACHE_KEY_PREFIX + longUrl);
if (cache != null) {
return LOCALHOST + toOtherBaseString(Long.valueOf(cache), decimal.x);
}
// 自增
long num = jedis.incr(SHORT_URL_KEY);
// 在数据库中保存短-长URL的映射关系,可以保存在MySQL中
jedis.set(SHORT_LONG_PREFIX + num, longUrl);
// 写入缓存
jedis.setex(CACHE_KEY_PREFIX + longUrl, CACHE_SECONDS, String.valueOf(num));
return LOCALHOST + toOtherBaseString(num, decimal.x);
}
/**
* 在进制表示中的字符集合
*/
finalstaticchar[] digits = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
/**
* 由10进制的数字转换到其他进制
*/
private String toOtherBaseString(long n, int base) {
long num = 0;
if (n < 0) {
num = ((long) 2 * 0x7fffffff) + n + 2;
} else {
num = n;
}
char[] buf = newchar[32];
int charPos = 32;
while ((num / base) > 0) {
buf[--charPos] = digits[(int) (num % base)];
num /= base;
}
buf[--charPos] = digits[(int) (num % base)];
returnnew String(buf, charPos, (32 - charPos));
}
enum Decimal {
D32(32),
D64(64);
int x;
Decimal(int x) {
this.x = x;
}
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(new ShortUrlUtil("localhost").getShortUrl("www.baidudu.com", Decimal.D32));
System.out.println(new ShortUrlUtil("localhost").getShortUrl("www.baidu.com", Decimal.D64));
}
}
}
推荐阅读:
微信扫描二维码,关注我的公众号
朕已阅
评论
管理世界2024 | 使用管理层讨论与分析测量「企业人工智能指标」
Tips: 公众号推送后内容只能更改一次,且只能改20字符。如果内容出问题,或者想更新内容, 只能重复推送。为了更好的阅读体验,建议阅读本文博客版, 链接地址 https://textdata.cn/blog/2024-04-19-ai-improve-firm-productivity/
大邓和他的Python
0
springboot第70集:字节跳动后端三面经,一文让你走出微服务迷雾架构周刊
创建一个使用Kubernetes (K8s) 和 Jenkins 来自动化 GitLab 前端项目打包的CI/CD流水线,需要配置多个组件。下面,我将概述一个基本的设置步骤和示例脚本,以帮助你理解如何使用这些工具整合一个自动化流程。前提条件确保你已经有:Kubernetes 集群:用于部署 Jenk
程序源代码
0
一站式解决方案:基于 Arthas 实现服务发现和权限控制
来源:juejin.cn/post/7281849496983994383👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接
小哈学Java
0
用 Shader 实现旗帜飘扬动画效果
我觉得对于刚入门 3D 编程的朋友来说,如果能够完成代码创建模型数据->创建材质->编写Shader动画这一系列,想必会有满满的成就感。今天就用 Cocos Creator 的 utils.MeshUtils.createMesh 接口,带大家感受一下这个流程。这个流程不仅可以用于新手学
COCOS
2
只写后台管理的前端要怎么提升自己
大厂技术 高级前端 Node进阶点击上方 程序员成长指北,关注公众号回复1,加入高级Node交流群本人写了五年的后台管理。每次面试前就会头疼,因为写的页面除了表单就是表格。抱怨过苦恼过也后悔过(虽然我现在已经心安理得的摆烂),但是站在现在的时间点
程序员成长指北
1
Java与lua互相调用简单教程
来源:网络👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:http://116.62.199.48/ ,新项目
小哈学Java
0
【送书福利】《Java面试八股文:高频面试题与求职攻略一本通》
先来唠唠最近粉丝面试回来跟我聊天,基本上都提到一个点,在面试过程中八股文占比很高(八股文70%、项目20%、10%算法)除了一些搞算法突出的厂除外。其实现在很多厂八股都是逐渐深入的方式来问,所以大家在学习的过程中,针对一些重点的内容,最好深入去学习,不然还是比较难应对这种追问式的问题。最近刚好从一位
Java后端技术
0
微服务与领域驱动设计,架构实践总结
来源:知了一笑👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:http://116.62.199.48/ ,新
小哈学Java
0