短网址系统设计总结
需求评估
- 输入数据:一个长网址、过期时间和一个自定义的别名
- 输出数据:自定义别名或者随机生成的短网址,过期时间之前访问都会被重定向到原始地址。
- 读多写少
实现原理:将短网址redirect到长网址(301/302跳转)
约束:
- 过期即失效
- 短网址唯一
- 支持自定义短网址
- QPS要求、低延迟、可靠性、安全性
系统设计
可行解
- 写
- 输入长域名,判断是否存在
- 生成一个未使用的短网址,并进行持久化
- 读
- 获取短网址,判断是否过期
- 正常则返回短网址
其他方面:
- 使用延迟删除策略清理过期数据
- 读时消重:返回的时候过滤重复元素
- 写时消重:写时判断以避免重复写入
- 短网址生成算法:
- UUID:无法保证唯一性
- 哈希:MurMurHash等方法,无法保证唯一性,考虑转为62进制
- ID:使用7位62进制,即长度为7,由大小写字母加数字共62个字符组成
- 雪花算法:转为62进制
- 用户自定义:记录正在使用的ID,写入时判断是否存在
MySQL表结构如下:
id | long_url | short_url | expire_time | create_time | delete_time |
---|
Redis键值设计:
k:长网址, v:短网址
吞吐量优化
- 水平扩展:使用Nginx做负载均衡
- 存储层:MySQL替换为持久化KV存储,比如RocksDB,若存在数据分析的需求,可以添加数仓
- 索引优化:两个方面
- 写入时判需要判断长网址是否存在
- 读取时根据短网址查询长网址
- 分片:短网址进行一致性哈希等方式计算分片位置。
- 缓存层:读多写少的系统使用缓存优化QPS
- 使用bloom filter检查长网址是否存储,短网址是否分配
- 直接在本地设计缓存
- 业务层
- 分布式ID生成需要考虑数据一致性问题
- 网络层:降低广域延迟
可靠性优化
- 存储层:考虑主从副本机制,增加数据可靠性
- 提供跨机房的数据冗余备份,通过log同步数据
- 监控业务集群,实现熔断、限流、扩容缩容等
安全性优化
- 避免使用自增,防止逐个遍历
- 防止DDos,对接口做限流,增加IP黑名单机制
短网址系统设计总结
https://l1n.wang/2022/系统设计/短网址系统设计总结/