如何把一个 100 字符的长 URL 缩短成 6 位短码?本文拆解短链接系统的底层逻辑:从 Base62 算法到分布式 ID 生成器,从 302 重定向策略到布隆过滤器防穿透。带你掌握支撑千亿级跳转的架构方案,文末附面试满分模板。

写在开头

前两天有个兄弟跟我复盘字节跳动二面,他被问到一个经典的系统设计题:

“我们要设计一个像 t.cn 或 dwz.cn 这样的短链接系统,每天要处理亿级的新增和跳转,你怎么设计?”

这哥们想都没想:“简单啊!把长链接拿去做个 MD5,取前 6 位当短码,存到数据库里。查询的时候根据短码查出长链接,直接跳转不就行了?”

面试官推了推眼镜,连发三问:

  1. “MD5 必然会有哈希碰撞,100 亿数据下两个不同长链生成了同一个短码,你让用户跳哪去?”
  2. “为了性能你肯定要加缓存,但如果有人恶意攻击,不停访问不存在的短码,你的数据库瞬间就会被打挂,怎么防?”
  3. “HTTP 状态码你选 301 还是 302?如果选错了,你的运营数据统计(点击量、来源)全得报废,你知道为什么吗?”

他当场宕机。

其实,这道题考的是“高并发系统的唯一性保证与全链路优化”。今天 Fox 带你拆解短链接系统的 3 种架构境界。

一、 核心博弈:HTTP 301 还是 302?

这是面试官考察你对业务理解的第一关。

  • 301 (Permanent Redirect): 永久重定向。浏览器会缓存跳转关系,下次访问直接跳,不经过你的服务器。
    • 优点: 节省服务器压力。
    • 致命缺点:****你拿不到点击数据了! 作为短链接服务,核心价值就是统计点击量、设备信息、地区等。一旦 301,你的后台统计全是 0。
  • 302 (Temporary Redirect): 临时重定向。每次访问都会经过短链接服务器。
    • 优点: 完美统计每一次点击,进行数据分析。

Fox 的结论: 除非服务器快崩了要保命,否则必须选 302。数据才是短链接系统的灵魂。

二、 算法之争:怎么生成那 6 位短码?

100 亿数据量,短码长度多少才够?

我们通常使用 Base62 编码(a-z, A-Z, 0-9)。

如果是 6 位短码,总容量是 亿;如果是 7 位,则是 万亿。对于 100 亿数据,6 位足矣。

境界 1:哈希算法(会有碰撞)

像 MD5 或 MurmurHash。

  • 痛点: 既然是哈希,就一定有碰撞。虽然几率小,但 100 亿量级下,碰撞是必然。
  • 补救: 发现碰撞后,在长链后面拼个随机字符串再重新哈希。但这会多出一次 DB 查询,性能受损。

境界 2:自增序列法(主流解法)

不搞哈希,直接给每个长链接分配一个唯一 ID。

  1. 第一个长链 ID 是 1,第二个是 2...
  2. 将 ID 转为 Base62 编码。比如 ID 100,000,000 转出来可能就是 6LAze。
  • 优点: 绝对唯一,永不重复。
  • 挑战:分布式 ID 的生成速度。

三、 架构实现:如何支撑千亿级数据?

1. 分布式 ID 生成器(发号器)

单机自增肯定不行。我们可以采用类似美团 Leaf 或推特 Snowflake 的方案:

  • 号段模式: 每次从数据库批量申请 10000 个 ID 缓存在内存里,用完再去申请。
  • 优势: 避免频繁请求数据库,支撑每秒万级以上的新增请求。

2. 读写分离与缓存策略

  • 写: 发号器生成短码 -> 存入数据库 -> 存入 Redis。
  • 读: 先查 Redis。短链接一旦生成就不会变,缓存命中率极高。
  • 布隆过滤器(Bloom Filter): 在访问 Redis 之前,先过一层布隆过滤器。如果布隆过滤器说这个短码不存在,直接拦截,防止缓存穿透打挂数据库。

3. 如何应对热点 Key?

比如某个大 V 发了一条微博,短链接瞬间被点爆。

  • 方案: 开启 Redis 的 Local Cache(二级缓存)。在本地 Tomcat 内存中缓存极热点的短链接,连网络 I/O 都省了。

四、 面试标准答案模板(直接背诵)

“针对短链接系统设计,我的核心思路是‘发号器机制 + Base62 编码 + 多级缓存策略’:

  1. 状态码选择: 采用 HTTP 302,确保每一笔点击流量都能经过后台,实现精确的业务数据统计。
  2. 生成逻辑: 舍弃有碰撞风险的哈希算法,采用分布式号段模式生成唯一自增 ID。将 ID 进行 Base62 编码,6 位短码即可支撑 568 亿数据量。
  3. 查询性能: 采用 Redis 缓存所有短码映射,由于短链接具有‘只读’属性,缓存命中率非常高。
  4. 系统安全: 在接入层部署 布隆过滤器,拦截恶意构造的非法短码请求,保护后端数据库不被穿透。
  5. 存储扩展: 针对百亿级数据,对数据库进行分库分表(按短码哈希分片),并配合 CDN 加速静态资源的访问。”

写在最后

技术面试考的从来不是你会不会用 MD5,而是你对数据碰撞、存储成本、以及全链路稳定性的掌控力。

能把一个简单的 a=b 问题,拆解成分布式 ID、缓存穿透防御、以及 HTTP 协议深度运用的系统方案,这才是架构师的功底。

更多推荐