1. 为什么需要短链接服务在开始设计之前我们需要理解短链接服务的核心价值。想象一下你在Twitter上分享一个亚马逊商品链接原始URL可能长这样https://www.amazon.com/dp/B08N5KWB9H/refsr_1_3?dchild1keywordswirelessearbudsqid1623345678sr8-3这种冗长的URL会带来三个实际问题在字符受限的场景如短信、推文会占用宝贵空间影响用户点击意愿长链接看起来不可信难以口头传播比如电话中念这个URL简直是噩梦短链接服务通过建立原始URL→短码的映射关系将上述链接转化为类似https://tinyurl.com/yckz7xts的形式。这种转换看似简单但要做到高性能、高可用需要考虑诸多工程挑战。2. 系统需求与指标拆解2.1 功能需求核心功能URL缩短输入长URL → 返回短URLURL还原访问短URL → 重定向到原始URL进阶功能自定义短码允许用户指定部分路径链接有效期设置点击统计与分析账户管理与链接分组2.2 非功能需求延迟缩短/还原操作 100ms可用性99.99%全年停机52分钟持久性短链接一旦创建永久有效吞吐量预计每天1亿次缩短操作约1157次/秒2.3 数据量估算假设每天新增1亿条短链接每条记录约500字节含元数据5年数据量1亿×500B×365×5 ≈ 91TB读写比例100:1每天100亿次访问3. 短码生成方案对比3.1 常用方法对比方案原理优点缺点哈希算法对原始URL取MD5等哈希值后截取无碰撞风险长度不可控需要查重自增ID使用数据库自增主键绝对唯一可预测暴露业务量随机字符串生成随机字母数字组合不可预测需要查重机制预生成池提前生成短码放入队列性能最佳需要维护池状态3.2 推荐方案62进制转换将自增ID转换为62进制a-z, A-Z, 0-9def base62_encode(num): charset abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 if num 0: return charset[0] res [] while num 0: res.append(charset[num % 62]) num num // 62 return .join(reversed(res))示例1000000000 → 15ftgG优势固定长度取决于ID范围无碰撞风险可逆运算便于调试4. 存储架构设计4.1 数据模型CREATE TABLE short_urls ( id BIGINT PRIMARY KEY AUTO_INCREMENT, short_code VARCHAR(10) NOT NULL UNIQUE, original_url VARCHAR(2048) NOT NULL, user_id INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP NULL, click_count INT DEFAULT 0, INDEX idx_short_code (short_code) );4.2 存储选型MySQL存储核心映射关系利用其强一致性Redis缓存热点数据布隆过滤器防穿透对象存储存放点击日志等大数据量内容4.3 分库分表策略按short_code首字母分片62个分片每个分片单独部署均匀分布写压力避免单表过大控制在1TB以内便于水平扩展5. 高并发优化方案5.1 缓存设计采用多级缓存架构客户端缓存HTTP 301永久重定向CDN边缘缓存缓存热门短链接内存缓存Redis集群存储近期访问记录缓存更新策略def get_original_url(short_code): # 先查Redis original_url redis.get(short_code) if original_url: return original_url # 查数据库 original_url db.query(SELECT original_url FROM short_urls WHERE short_code ?, short_code) # 回填缓存 if original_url: redis.setex(short_code, 3600, original_url) return original_url5.2 限流措施API网关层令牌桶算法限流1000请求/秒/IP数据库层读写分离1主10从短码生成服务预生成短码缓冲池6. 关键问题与解决方案6.1 如何防止短码被猜解方案1增加短码长度6位→8位方案2在62进制转换前混入随机数方案3对连续错误访问实施封禁6.2 如何处理URL失效定期扫描expires_at字段软删除异步清理机制保留短码但返回410 Gone状态6.3 如何应对热点链接动态调整CDN缓存策略本地缓存自动预热限流降级方案7. 监控与运维设计7.1 核心监控指标服务可用性HTTP 5xx错误率重定向延迟P99 50ms存储层负载CPU/内存/磁盘IO短码冲突率应0.001%7.2 日志分析流水线访问日志 → Flume采集 → Kafka队列 → Spark实时计算 → → 实时看板Grafana → 离线分析HDFSHive8. 实际部署建议8.1 服务器配置Web层10台4核8G容器K8s自动扩缩缓存层Redis Cluster6节点32G内存/节点数据库MySQL Group Replication3写节点8.2 灾备方案多可用区部署定期快照备份RDS自动备份短码生成服务双活部署我在实际部署时发现使用Nginx的proxy_cache能显著降低后端压力。以下是一个实测有效的配置片段proxy_cache_path /var/cache/nginx levels1:2 keys_zoneshorturl_cache:10m inactive60m; server { location / { proxy_cache shorturl_cache; proxy_cache_valid 200 301 302 10m; proxy_pass http://backend; } }对于自定义短码功能建议实施严格的审核机制。我们曾遇到有人注册含敏感词的短码后来增加了以下校验规则屏蔽常见敏感词列表禁止连续数字防电话号码最小长度限制不少于4字符短链接服务的重定向策略也值得注意。根据我们的A/B测试301永久重定向SEO友好但不利于统计302临时重定向便于实时统计但增加后端压力 最终我们采用混合方案普通链接用301商业推广链接用302。