设计一个短链系统, 每日写入量百万,访问量千万 ,要求通过短链找到长链 10ms内,同时不能重复插入长链
设计一个短链系统,使用 Redis 作为缓存 提供高性能读写,数据库(如 MySQL)持久化存储,结合 分布式 ID 生成器 和 Base62 编码 生成唯一短链。核心思路:短链映射长链通过键值对存储,Redis 保证低延迟查询,数据库加唯一索引防止重复插入。
关键需求与解决方案
- 性能要求:
- 每日写入量百万:约 11.6 次/秒,需高效写入。
- 访问量千万:约 115 次/秒,需低延迟查询。
- 10ms 内响应:Redis 单线程 O(1) 查询满足需求。
- 功能要求:
- 短链找长链:键值映射,短链为 key,长链为 value。
- 不重复插入长链:数据库唯一索引 + Redis 查重。
系统设计
1. 架构组件
- 客户端:用户提交长链或访问短链。
- 应用服务:短链生成与查询逻辑(Java/Spring)。
- Redis:缓存短链-长链映射,高频读写。
- MySQL:持久化存储,防数据丢失。
- ID 生成器:分布式唯一 ID(如雪花算法)。
2. 数据结构
- Redis:
- Key:短链(如 abc123)。
- Value:长链(如 https://example.com/...)。
- MySQL:
- 表:short_url。
- id:自增主键。
- short_url:短链(唯一索引)。
- long_url:长链(唯一索引)。
- create_time:创建时间。
- 表:short_url。
3. 核心流程
生成短链
- 接收长链:用户提交 https://example.com/...。
- 查重:
- 在 MySQL 查询 long_url,若存在,返回已有短链。
- Redis 加布隆过滤器(可选),快速排除不存在的长链。
- 生成短链:
- 用雪花算法生成唯一 ID(如 64 位)。
- ID 转为 Base62(0-9, a-z, A-Z),缩短长度(如 abc123)。
- 存储:
- 插入 MySQL(short_url=abc123, long_url=...),唯一索引防重复。
- 同步写 Redis(SET abc123 "https://...")。
- 返回:短链 http://short.com/abc123。
查询长链
- 接收短链:用户访问 http://short.com/abc123。
- 查询 Redis:
- GET abc123,O(1) 操作,<1ms。
- 若命中,返回长链。
- 回查 MySQL:
- 若 Redis 未命中,查 MySQL,加载到 Redis 并返回。
- 跳转:重定向到长链。
4. 性能优化
- Redis 集群:分片存储,应对千万访问。
- 异步写入:生成短链后,异步同步 MySQL,降低写入延迟。
- 缓存预热:高频短链预加载到 Redis。
- TTL:短链设过期时间(如 30 天),自动清理。
满足需求验证
- 写入量(百万/天):
- Redis 写 QPS 可达万级,11.6 次/秒轻松支持。
- MySQL 异步写入,单表支持百万级数据。
- 访问量(千万/天):
- Redis 查询 <1ms,集群支持 115 次/秒以上。
- 10ms 内响应有余。
- 不重复插入:
- MySQL long_url 唯一索引,插入冲突抛异常。
- Redis 查重提前拦截。
延伸与面试角度
- 扩展性:
- 分布式部署:多节点服务 + Redis 集群,应对更高流量。
- 短链长度:Base62 可调进制,ID 空间支持亿级。
- 一致性:
- Redis 宕机回查 MySQL,保证数据不丢。
- 异步写加重试,确保 MySQL 最终一致。
- 高可用:
- Redis 主从 + 哨兵,MySQL 主从复制。
- 冲突处理:
- 雪花算法保证 ID 唯一,数据库索引防长链重复。
- 优化点:
- 布隆过滤器减少无效查重。
- CDN 加速短链跳转。
总结
短链系统用 Redis 提供高性能读写,MySQL 持久化存储,雪花算法 + Base62 生成唯一短链。Redis 查 <1ms 满足 10ms 要求,数据库唯一索引防重复。每日百万写、千万访轻松支持。面试时,可画架构图或强调 Redis 性能,展示设计能力。