# 让你设计一个短链系统,怎么设计?

7 min read
Table of Contents

让你设计一个短链系统,怎么设计?

短链系统设计面试参考答案

【核心定义】

短链系统是一个将原始长URL通过哈希算法映射为短字符串,并通过重定向服务实现访问跳转的高并发分布式系统。

【关键要点】

  1. 核心功能拆解

    • 短链生成:将长URL转换为唯一短码(如7位字符)
    • 存储映射:建立短码→长URL的键值对存储
    • 重定向服务:接收短链请求,返回302重定向到原始URL
    • 访问统计:记录点击量、来源等分析数据
  2. 系统架构分层

    • 接入层:负载均衡、限流、缓存
    • 业务层:短链生成服务、重定向服务
    • 数据层:分布式KV存储(Redis集群)+ 持久化存储(MySQL/NoSQL)
    • 监控层:实时统计、报警、日志分析
  3. 核心算法选择

    • 哈希算法:MurmurHash/Base62编码
    • 唯一ID生成:雪花算法(Snowflake)、数据库自增ID、Redis原子操作
    • 冲突解决:布隆过滤器预判 + 重试机制

【深度推导/细节】

短链生成方案对比

方案A:哈希算法(如MD5截断)

Step 1: 对长URL计算MD5哈希值
Step 2: 取前8字节转换为Base62编码(62^8 ≈ 218万亿种组合)
Step 3: 检查是否已存在(布隆过滤器快速判断)
Step 4: 若冲突,添加盐值重新哈希或使用备用方案

痛点:哈希冲突概率虽低但需处理,相同URL会生成不同短链

方案B:分布式ID+编码转换

Step 1: 使用雪花算法生成全局唯一ID(64位)
Step 2: 将十进制ID转换为62进制字符串
Step 3: 直接存储映射关系,天然无冲突

优势:无冲突、可反解、相同URL可复用

高并发重定向优化

请求流程:
1. 用户访问 https://s.cn/abc123
2. Nginx负载均衡到最近节点
3. 查询Redis缓存(命中率>99.9%)
4. 若缓存未命中,查询数据库并回填缓存
5. 返回302重定向头,Location字段为原始URL
6. 异步记录访问日志到消息队列

存储设计细节

-- MySQL表结构
CREATE TABLE short_url (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
short_code VARCHAR(10) UNIQUE,
original_url VARCHAR(2048) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NULL, -- 支持过期时间
click_count INT DEFAULT 0,
INDEX idx_short_code(short_code),
INDEX idx_expires(expires_at)
);
-- Redis键设计
SET short:abc123 "https://original-long-url.com/very-long-path"
EXPIRE short:abc123 2592000 -- 30天过期

【关联/对比】

与普通URL重定向系统的区别

维度短链系统普通重定向
核心目标空间压缩 + 高并发跳转简单的URL转发
并发量级百万QPS级别万级QPS
存储要求海量映射关系 + 缓存少量配置
功能扩展统计、防刷、过期控制基础跳转

与分布式ID生成系统的关联

  • 短链系统依赖分布式ID生成器保证唯一性
  • 可采用同一套ID生成基础设施(如美团Leaf、百度UidGenerator)

『面试官追问』

  1. 如何防止短链被恶意刷量?

    • 用户维度限流:IP/UserID频率控制
    • 短链维度限流:热门短链单独限流
    • 验证码机制:可疑访问要求验证
    • 黑名单系统:恶意IP实时封禁
  2. 短码长度为什么通常是6-8位?

    • 6位Base62:62^6 ≈ 568亿,满足中等规模需求
    • 7位:62^7 ≈ 3.5万亿,满足大型系统需求
    • 8位:62^8 ≈ 218万亿,超大规模需求
    • 权衡:短码越短用户体验越好,但容量越小
  3. 如何处理相同长URL重复生成?

    • 方案一:先查缓存,存在则直接返回已有短链
    • 方案二:对长URL做MD5作为数据库唯一索引
    • 方案三:允许重复但提示用户已存在(如百度短链)
  4. 系统如何扩容?

    • 水平分片:按短码首字母或哈希值分库分表
    • 读写分离:重定向读多写少,分离部署
    • 多级缓存:L1本地缓存 + L2 Redis集群 + L3数据库
    • 服务拆分:生成服务与重定向服务独立扩缩容
  5. 如何设计过期清理机制?

    • 惰性删除:访问时检查过期时间
    • 定时任务:每天凌晨清理过期数据
    • 分片清理:避免单次清理数据量过大
    • 软删除标记:先标记后异步物理删除

【版本差异/演进考虑】

V1.0 最小可行方案

  • 单数据库 + Redis缓存
  • 简单的哈希算法生成短链
  • 基础的重定向功能

V2.0 高可用方案

  • 数据库主从复制 + Redis集群
  • 引入分布式ID生成器
  • 添加访问统计和过期功能

V3.0 企业级方案

  • 多数据中心部署
  • 智能防刷和风控系统
  • 实时大数据分析平台
  • API开放平台支持

V4.0 平台化方案

  • 自定义短码功能
  • 品牌域名支持
  • 团队协作和权限管理
  • 深度集成营销工具链

设计亮点总结:

  1. 采用分布式ID方案避免哈希冲突,保证唯一性
  2. 多级缓存设计使重定向响应时间<5ms
  3. 读写分离架构支撑亿级日PV
  4. 完善的监控和风控体系保障业务安全
  5. 模块化设计支持平滑演进和功能扩展
My avatar

文章看完了,不打算去别的篇章转转吗?👀 感谢你的耐心阅读!如果你有问题想探讨,或者发现了文中的 Bug,请务必通过页脚的链接联系我


More Posts

# 让你设计一个 RPC 框架,怎么设计?

11 min read

RPC(Remote Procedure Call)框架是一种允许程序调用位于不同地址空间(通常是另一台机器上)的过程或函数的通信协议实现,其核心目标是让远程服务调用像本地调用一样简单透明。

Read

Comments