基于 Nestjs + redis + Mysql 搭建的短链服务,对外提供生成短链及获取长链接口。
基于 62 进制的字符串与数据库 ID 的转换,由于短链路径不能超过 8 个字符,本项目中预留 7 个字符作为短链生成内容(最多生成 62 的 7 次方条数据),第一个字符作为 hash 值(用于判断请求打到哪个 DB 节点)
基于长链生成短链
curl -X POST -d "longUrl=http://www.baidu.com" https://f-xj.cn/shortUrl
回包结构
{
"data": "http://f-xj.cn/1b" //
}
基于短链换回长链
curl https://f-xj.cn/shortUrl?shortUrl=https://f-xj.cn/1b
回包结构
{
"data": "http://www.baidu.com" //
}
架构说明
- gateway 为云开发网关接入层,可以提供云上资源(如本项目中云托管)的 HTTP 访问,支持自定义域名,路由配置,就近接入访问等能力。
- 云托管为云上基于容器资源的托管平台,项目服务部署在该资源上,拥有版本灰度,流量调节,自动扩容等能力。
- 基于 redis 实现的布隆过滤器(使用 bloom-redis 库),用于短链换取长链接口时,检查短链是否可能在 DB 中,拦截一定不在 DB 的请求。
- 基于 redis 做接口的缓存设计,写入长短链映射至 DB 时,同时写入 Redis 缓存(可设置有效期),读取映射时优先读缓存,未获取到则查 DB。
考虑大数据量情况,通过分布式部署多个 DB 来缓解压力(本项目引入 2 个 DB),通过一致性 hash 保证写入与访问的是同个 DB,详细描述如下
- 将原域名哈希成 0,1 作为哈希值 hash_val
- 用 hash_val 定位到对应 DB。
- 将原域名插入数据库,获取短域名 shortUrl。将 hash_val 和 short_url 拼接为最终短域名 final_short_url(长度最多为 8)返回。
- 取 final_short_url 的第 1 个字符作为 hash_val
- 用 hash_val 定位到对应 DB
- 用 final_short_url 中剩余位作为 short_url 找到表中映射关系,将原域名 original_url 返回给用户
- 数据库账密,平台提供的环境变量注入方式,避免被泄漏。
- 防恶意攻击 DDOS,bloomfilter 能拦截大量无效请求
- 读缓存,Redis 减少 DB 压力
- 旁路降级,Redis 异常不影响请求访问 DB(但可能缓存击穿问题)
- 容器 Pod 服务多节点,DB 多节点,减少单点问题
https://leetcode-cn.com/circle/discuss/EkCOT9/ https://xie.infoq.cn/article/483fcfbe3f942cb1fa9d9ce20