“我正在参加「掘金·启航计划」”
需求背景
在业务平台发送短信时,因短信内容存在长度限制,因此需要一个短链接服务,将原始链接进行编码缩短。
这种营销短信在【活动大促】期间 大家应该都收到过,短信有最大字符限制,而且为了更好的观感体验,短信里的链接一般都很短。现成的短链接生成服务也比较多,比如新浪、百度、reduce等。
一、短链接原理
我们点击短链接会发起一个 GET 方式的 HTTP 请求,当请求到对应的 API 后,会解析短链接里的标识获取到对应的长链接,然后重定向到长链接,这样整个流程就结束了。
比如我生成了一个短链接:shorturl-test.tech.com/wX,下面是请求短链接时对应的代码信息:
@PathBinding("/{code}")
public void trigger(String code) {
if (CommonUtil.isNullOrEmpty(code)) {
return;
}
// 编码转id
Long id = PECode.decode(code);
if (id == null) {
return;
}
// 查询短链接
ShortInfo info = shortService.getShortInfo(id);
if (info == null || info.getStatus() != 1) {
return;
}
// 增加PV次数
frequencyQueue.addFrequency(info.getId());
// 重定向
response.sendRedirect(info.getUrl());
}
对应后台界面
二、短链的加密算
自定义array数组,打乱该字符数组的组合顺序,可以得到不同的转换结果
{ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g',
'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', '8', '5', '2', '7', '3', '6', '4', '0', '9', '1',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X',
'C', 'V', 'B', 'N', 'M', '@', '!','$','-' } 长度为66
1.原url存储到数据库里返回自增长id(long)
2.然后对id进行取模mod进行编码,根据取模结果为下标拿出数组中结果
3.自增ID再除以自定义arr数组长度,是否>=1, 如果是的话一直循环2步骤,结果都放入到栈中。
4.栈不为空,挨个弹出栈中值进行最终结果拼接(最多可以表示2^66种情况)
理论上重复的概率非常小,自增ID最大为Long.Max
三、一些细节
1.目前仅统计PV,没有统计UV。后续方案参考:uv通过redis hash结构实现,每天同步落库会有延迟。
2.需要转为短网址的原始地址(注:原始地址可能存在中文、乱码、符号等,建议先进行URL编码处理。
3.如果短链接请求频繁,可以借助 redis 做对应的缓存优化。