设计 URL Shortener

发布: (2026年3月1日 GMT+8 12:44)
5 分钟阅读
原文: Dev.to

Source: Dev.to

要求

核心

  • 用户可以将长 URL 创建为短 URL。
  • 访问短 URL 会重定向到原始 URL。

可选

  • 自定义别名(例如 short.ly/myname
  • 链接的过期时间
  • 分析(点击次数、地理位置、设备信息)
  • 高可用性(服务几乎不宕机)
  • 低延迟重定向(重定向应即时完成)
  • 大规模(数百万条 URL,数十亿次重定向)
  • 持久存储(即使服务器崩溃也不会丢失数据)

假设与负载估计

  • 10 M 每月新增 URL
  • 1 B 每月重定向
  • Read‑to‑write ratio: ~100:1

含义

  • 系统以读取为主。
  • 缓存至关重要。
  • 数据库必须水平扩展。
  • 写入可控;读取可能激增。

高层架构

Client ──► Load Balancer ──► URL Generation Service ──► Key‑Value Store
                     │                                 │
                     ▼                                 ▼
                Redirection Service ◄── Cache (Redis) ◄───

写入路径(创建短链接)

  1. POST /shorten 请求到达负载均衡器。
  2. URL 生成服务创建唯一的短码。
  3. 映射(short_code → long_url)存储在键值数据库中。
  4. 短链接返回给客户端。

读取路径(重定向)

  1. GET /{short_code} 请求命中负载均衡器。
  2. 重定向服务检查缓存(例如 Redis)。
  3. 缓存命中: 立即返回 HTTP 301/302 重定向。
  4. 缓存未命中: 从数据库获取映射,填充缓存,然后进行重定向。

API 规范

创建短链接

POST /shorten
Content-Type: application/json
{
  "long_url": "https://example.com/very/long/url",
  "custom_alias": "optional",
  "expiry": "optional timestamp"
}

响应

{
  "short_url": "https://short.ly/abc123"
}

重定向

GET /{short_code}

响应 – HTTP 301 或 302 重定向到原始 URL。

ID 生成策略

自动递增 ID + Base62

  • 递增一个数值 ID。
  • 将 ID 转换为 Base62(a‑zA‑Z0‑9)。
  • 保证唯一性,确定性,且易于扩展。

基于哈希

  • 对长 URL 进行哈希并取前 6–8 个字符。
  • 问题: 可能出现冲突 → 需要冲突解决。

复合(时间戳 + 机器 ID + 序列)

  • 在多个服务器并发生成 ID 时很有用。
  • 提供高可扩展性和唯一性。

分片

  • 分片键: hash(short_code) % N
  • 优势: 均匀分布,防止热点,查询简单。

数据库复制

  • 主节点: 处理写入(新的短链接)。
  • 只读副本: 提供重定向服务。

优势

  • 读取占据大部分流量 → 可以独立扩展读取。
  • 提高可用性;如果主节点故障,可提升副本为主节点。

缓存层

  • 缓存键: short_code → long_url.
  • 常见缓存: Redis 或内存存储。

缓存工作流

  1. 检查 Redis。
  2. 命中 → 立即重定向。
  3. 未命中 → 查询数据库,更新缓存,然后重定向。

缓存调优

  • 条目 TTL(可选)。
  • LRU 驱逐策略。
  • 为热门 URL 预热缓存。

分析与点击计数

同步更新点击计数会减慢重定向速度。

更佳方案

  1. 将点击事件发送到消息队列(Kafka、RabbitMQ 等)。
  2. 后台工作者消费事件并异步更新分析数据。

优势

  • 保持重定向路径快速。
  • 将分析与用户体验解耦。
  • 支持独立扩展。

边缘情况与权衡

  • 自定义别名冲突: 拒绝或提示用户选择其他别名。
  • 短码冲突: 使用确定性生成(自动递增)或通过重试解决冲突。
  • 恶意/垃圾 URL: 集成 URL 安全检查(例如 Google Safe Browsing)。
  • 链接过期: 返回 410 Gone 或自定义错误页面。
  • 301 与 302: 大多数服务倾向于使用 302,以便以后可以更改目标地址。

摘要

URL 缩短服务是典型的读密集型系统。通过激进的缓存、只读副本以及异步分析来优化重定向路径,对于实现低延迟和高可扩展性至关重要。设计决策——例如 ID 生成、分片和缓存策略——必须在唯一性、性能和运维简易性之间取得平衡。

0 浏览
Back to Blog

相关文章

阅读更多 »

国家疫苗预约与接种系统

🌱 它是如何开始的 几年前,我参加了一场系统设计面试。面试官给了我这样一个情景:> 设计一个全国疫苗预约系统…

防线:三系统,而非单一

三个系统,而不是一个。“Rate limiting” 常被用作一个统称,指任何拒绝或放慢请求的行为。实际上,它包含三种不同的机制……

不糟糕的语义失效

缓存问题 如果你在 Web 应用上工作了一段时间,你就会了解缓存的情况。你加入缓存,一切都变快了,然后有人……

2026年企业 Web 开发终极指南

企业网页开发在过去十年中经历了巨大的演变。随着企业对数字平台的依赖日益增加,创建可扩展的、安全的、以及 h...