一篇文章说清楚,短链服务实现思路与简单示例
一、整体思路概述
生成短链
对输入的长链进行校验,避免恶意链接或无效链接。
使用非加密型哈希算法(如 MurmurHash3)对长链进行哈希计算,得到 32 位哈希值。
将哈希值转换成 62 进制字符串(字符集通常是
[0-9][A-Z][a-z]
),以此作为短链标识。可能存在哈希冲突的情况:可拼接随机字符串或分布式 ID 重新生成。
将短链与长链的映射关系存储在数据库及缓存(可选)中。
重定向访问
用户访问类似
https://yourdomain.com/s/xxxx
的短链。服务端根据短链标识去数据库或缓存查询对应长链。
若存在对应的长链,就使用 HTTP 302 做临时重定向,并统计访问信息(IP、时间、来源等)。
监控与统计
在重定向逻辑中,可以调用监控服务收集短链访问信息。
可以通过直接写数据库或异步化的方式(消息队列/日志)积累访问日志。
后台可基于此数据进行 PV/UV、来源、浏览器类型等多维度统计分析,做成可视化报表。
二、示例代码
下面以 Spring Boot 为例,演示一个最简化的短链重定向控制器和哈希生成工具类。
1. 工具类:MurmurHashUtil
public class MurmurHashUtil {
// 这里以 MurmurHash3 32-bit 版本做演示,使用 Google Guava 或相似库
public static long hash32(String data) {
int seed = 0x1234ABCD;
return Hashing.murmur3_32_fixed(seed)
.hashUnencodedChars(data)
.padToLong();
}
// 将 32 位整型转换为 62 进制字符串
public static String toBase62String(long hashValue) {
// 考虑到 hashValue 可能为负数,可以做一下取绝对值处理
long num = hashValue & 0x00000000ffffffffL;
String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
StringBuilder sb = new StringBuilder();
while (num > 0) {
int remainder = (int) (num % 62);
sb.append(chars.charAt(remainder));
num = num / 62;
}
return sb.reverse().toString();
}
}
hash32(String data)
使用 MurmurHash3 算法生成 32 位哈希值。toBase62String(long hashValue)
将哈希值转为 62 进制字符串,以减少长度并支持大小写数字组合。
2. Controller:ShortController
/**
* @author zhiweicoding.xyz
* @date 28/12/2024
* @email diaozhiwei2k@gmail.com
*/
@Slf4j
@RestController
@RequestMapping("/s")
public class ShortController {
@GetMapping("/{shortKey}")
public void redirectUrl(@PathVariable("shortKey") String shortKey,
HttpServletRequest request,
HttpServletResponse response) throws IOException {
log.info("shortKey: {}", shortKey);
// 1. 根据短链 key 查询长链
//假设去获取来的
String longUrl = "https://zhiwei.plus/archives/1733061010367";
if (longUrl == null) {
// 可返回一个 404 页面
response.sendError(HttpServletResponse.SC_NOT_FOUND, "短链不存在");
return;
}
// 2. 统计监控数据 (访问者ip, 浏览器信息, referrer 等)
// urlMonitorService.collect(shortKey, request);
// 3. 做 302 临时重定向
response.setStatus(HttpServletResponse.SC_FOUND); // 302
response.setHeader("Location", longUrl);
}
}
通过
@GetMapping("/{shortKey}")
捕获短链访问请求。从数据库/缓存获取真实长链地址,若不存在则返回 404。
若存在则执行 302 重定向,并在此处可调用监控服务收集访问数据。
3. 生成短链逻辑示例
在实际生产环境中,生成短链流程通常类似下面伪代码:
public String generateShortKey(String longUrl) {
// 1. 合法性校验,排除黑名单域名/过期链接等
// ...
// 2. 计算哈希
long hashVal = MurmurHashUtil.hash32(longUrl);
String base62 = MurmurHashUtil.toBase62String(hashVal);
// 3. 检查是否冲突(根据base62查询数据库,若已存在且长链不同,冲突)
// 若冲突,则拼接随机字符串或分布式ID重新计算
// ...
// 4. 保存数据库 & 缓存
// ...
return base62;
}
三、监控与统计思路
最简单:直接在
ShortController
里统计点击量,或者更新数据库字段visit_count
。进阶:将访问日志(ip、referer、ua 等)插入数据库或写入消息队列异步处理,避免高并发下的数据库压力。
高级:配合大数据平台进行流式或离线统计,做成可视化报表。
四、总结
核心要点
哈希生成:MurmurHash + 62 进制转换,生成较短的标识字符串。
短链->长链映射:使用关系型数据库(MySQL/PostgreSQL)或者 NoSQL(Redis)进行存储。
重定向:使用
302
临时重定向,让浏览器下次依旧先访问短链,从而方便后续统计分析。监控统计:收集访问信息,用于广告效果追踪、业务数据分析。
可扩展方向
自定义短链、多域名映射、防止恶意爬虫、访问权限控制、接口限流等。
结合缓存、分布式部署提升吞吐量和可用性。