短链服务
短链服务
本文柯苏远写于2024年5月11日 12点0分
背景
上个月对接了短信厂商的发送短信接口,但是由于短信里会存在链接,链接太长影响影响用户看短信的内容。为了优化用户短信观看体验,所以有了这个需求,主要是做一个映射,将原先的长链接映射成一个短链接,用户通过访问短链接再重定向到原先的长链接。
产品参考了友商短链长度之后,决定将短链的长度固定在24个字符。
短链服务设计
我可以映射的长度
什么叫我可以映射的?
由于产品已经将短链的长度固定在24个字符,https://
就已经包含8个了,还有16个长度要包含域名以及待跳转长链对应的字符串。由于目前公司所购买的所有域名中最短的一个是9个字符,形式是:xxx.yyyyy
,所以还剩7位,但是域名和长链接对应的字符串之间需要/
来分割,最后我能用的长度就只剩下6位了。
最后整个短链的格式就是:https://xxx.yyyyy/ABCDEF
最后的ABCDEF
就是长链对应的字符串映射。
定义一下短链名词说法
短链 = 短链域名 + 6位短链字符串(短链字符)
短链服务的时序图
时序图中的关键步骤
在时序图中就包含了短链服务的所有交互,这里记录下短链服务中的关键步骤和思想。
1. 根据base62算法生成短链字符
base62算法:
62是指62个字符,分别是26个小写字母,26个大写字符以及10个数字字符,总共就是62个。
这里说的base62算法更像是一种62进制。
举个例子: base62的字符串是:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
如果当前数字是5,那么我用base62怎么表示? 步骤就是用5对62取余,然后去这个字符串对应下标获取对应字符,最后获取到的答案是
F
。同理,128用base62怎么表示?同样的步骤,得到答案是
CE
。
相关代码:
private static final String BASE62_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
public static String encode(long num) {
StringBuilder sb = new StringBuilder();
do {
int remainder = (int)(num % 62);
sb.insert(0, BASE62_CHARACTERS.charAt(remainder));
num /= 62;
} while (num != 0);
return sb.toString();
}
2. 6位短链字符串能表示多大的数字?
上面介绍过短链字符串只给我留了6位长度,这6位对应的是base62这个62进制。 那么这6位字符对应的最大十进制怎么算?
6位对应的最大base62是:999999
,在base62中9表示的是61,所以6位base62能表示的最大值是:62^6-1
(这个是进制转换的知识,可以网上找找,类比二进制的。)
62^6-1
约等于 568_0023_5583,有568亿的数据量,够用了,单表数据就几千万。
3. 短链字符串对应的十进制数字怎么来?
在我们的实现中是直接取的短链表主键(long类型)。
由于我们的业务量并不大,所以单库单表够用了,如果单表数据量太多就要进行分表设计了。
后面如果我们业务的短链表要进行分表,那么要是根据时间范围进行归档,因为按理说一个短链发出去是有有效期的概念的,虽然我们的业务没有涉及,哈哈
4. 短链表的设计
CREATE TABLE `short_url` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '短链表id',
`long_url` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原始长链',
`long_url_md5` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '原始长链的md5',
`short_url_str` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '6位短链字符串',
`status` int UNSIGNED NOT NULL DEFAULT 0 COMMENT '0: enable 1: disable',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uk_md5`(`long_url_md5`) USING BTREE,
UNIQUE INDEX `uk_short_url_str`(`short_url_str`) USING BTREE
)
总结
感谢公司提供了这样一个场景,让我接触到了短链服务的设计,挺锻炼人的,让我获得了对应的成长。 期间也遇到了些许问题,也是在老大帮助下解决了。
短链服务归根结底其实就是维护一个长链和短链的映射关系,然后可以通过不同方式实现,不一定非得我文章中的方式。 还有就是base62这种62进制思想挺有意思的。
转载自:https://juejin.cn/post/7367292352275562535