type
status
date
slug
summary
tags
category
icon
password
短URL

问题定义
核心功能:
- 输入长网址:
https://www.example.com/very/long/path/to/some/resource?param1=value1¶m2=value2
- 输出短网址:
https://t.ly/abc123
- 短网址跳转到原始长网址
典型场景:
- 微博/Twitter的链接缩短
- 二维码生成(短网址更容易编码)
- 短信/邮件中的链接
- 营销活动追踪
301 vs 302 redirect区别
301永久重定向
想象你搬家了,从老地址A搬到新地址B,而且再也不会回到A了。你会:
- 去邮局办理永久地址变更
- 告诉所有朋友以后直接去B找你,不要再去A了
- A地址的房子可能被拆了或者给别人了
这就是301:这个资源永远不在原来的地方了,以后直接去新地方找。
302临时重定向
想象你只是临时出差到B地,但A还是你的家,你会:
- 告诉朋友"我现在暂时在B,但还是要先联系A"
- 朋友每次找你都先打A的电话,然后被告知去B
- 过段时间你回来了,还是在A
这就是302:我现在临时在别的地方,但请继续联系我的原地址。
🌐 互联网中的实际应用
浏览器的"记忆"差别
301的浏览器行为:
浏览器记住了"A已经永久搬到B了",下次用户输入A的网址,浏览器直接跳转到B,甚至不问服务器。就像你记住了朋友的新地址,直接去新地址找他。
302的浏览器行为:
浏览器每次都要先问A:"你现在在哪里?"A回答:"我临时在B",然后浏览器再去B。每次都要问一遍。
搜索引擎的理解差别
301的SEO影响:
- Google认为:原网页已经不存在了,把所有权重给新网页
- 就像店铺搬迁,所有顾客和声誉都转移到新店
- 原网页在搜索结果中消失,新网页继承排名
302的SEO影响:
- Google认为:原网页只是临时不在,保持原网页的权重
- 就像店铺临时装修,顾客知道还会回来,不改变对老店的印象
- 原网页保持搜索排名,新网页不获得权重
🔄 URL短网址服务中的选择
为什么短网址通常用302?
统计数据的需要:
假设你开了一家咖啡店,门口放了指路牌指向你的店。你想知道:
- 每天有多少人看了指路牌
- 什么时间人最多
- 客人从哪里来
如果用301(永久重定向):
- 看过一次指路牌的人,下次直接去咖啡店,不再看指路牌
- 你就统计不到后续的访问数据了
如果用302(临时重定向):
- 每个人每次都要看指路牌才能找到咖啡店
- 你能统计到每一次访问
灵活性的需要:
短网址服务就像一个"智能指路牌":
- 今天指向A网站
- 明天可能需要指向B网站(比如活动结束了)
- 用302,改变目标立即生效
- 用301,浏览器记住了旧目标,可能还会去旧地方
什么情况下用301?
网站搬迁:
- 公司网站从 oldcompany.com 搬到 newcompany.com
- 这是永久性的,旧域名不再使用
- 希望搜索引擎把旧网站的权重转移给新网站
URL标准化:
- 同一内容有多个网址:example.com 和 www.example.com
- 选择一个作为标准,其他的301重定向过去
- 避免搜索引擎认为是重复内容
⚡ 性能差异
301的性能优势
用户第一次访问:
- 浏览器请求短网址
- 服务器返回301和目标网址
- 浏览器记住这个重定向关系
用户第二次访问:
- 用户输入短网址
- 浏览器直接跳转到目标网址(不请求服务器)
- 速度更快,服务器压力更小
302的统计优势
用户每次访问:
- 浏览器请求短网址
- 服务器记录访问数据
- 服务器返回302和目标网址
- 统计数据完整准确
🎯 选择决策
短网址服务选择302的原因:
- 数据价值:每次点击都能被统计,这是短网址服务的核心价值
- 灵活控制:可以随时改变目标,做A/B测试,地域分流
- 商业需求:广告跟踪、转化分析、用户行为分析
其他场景选择301:
- 网站迁移:SEO权重转移比统计更重要
- 性能优先:不需要每次都经过中间服务器
- 用户体验:减少跳转延迟
💡 关键洞察
301和302的本质区别:
- 301:告诉所有人"我永远搬走了,以后直接去新地方找我"
- 302:告诉所有人"我临时在别处,但还是通过老地方联系我"
业务决策的核心:
- 需要控制和统计 → 302
- 需要性能和SEO → 301
这个选择反映了不同的业务优先级:是要完整的数据控制,还是要更好的性能和搜索引擎优化。
Hash
核心就是要存一个 <shortURL, fullURL>关系
最好拿一个表来存
🎯 两种方案的核心思路
Hash + Collision Resolution(哈希+冲突解决)
核心思想:把长网址"压缩"成短码
- 输入同样的长网址 → 得到同样的短码
- 就像给每个长网址计算一个"指纹"
- 不同的长网址可能产生相同的"指纹"(冲突)
Base62 Conversion(Base62编码)
核心思想:给每个长网址分配一个唯一的数字ID,然后转换成短码
- 每个新的长网址 → 分配下一个数字(1,2,3,4...)
- 把数字转换成62进制表示(用a-z,A-Z,0-9)
- 就像银行给每个账户分配唯一账号

🔍 详细对比分析
数据存储差异
Hash方案的存储:
Base62方案的存储:
重复URL的处理方式
Hash方案:
- 用户输入相同长网址 → 返回相同短码
- 好处:节省存储空间
- 问题:无法区分不同用户、不同时间的相同URL
Base62方案:
- 用户输入相同长网址 → 每次都生成新的短码
- 好处:每个短码都是独立的,便于统计和管理
- 问题:相同内容会产生多个短码,占用更多存储
🎲 冲突问题的本质差异
Hash冲突
什么是冲突:不同的长网址产生了相同的哈希值
解决方案复杂性:
- 检测冲突:每次生成短码都要查数据库确认是否已存在
- 解决冲突:加盐重新哈希,或者在原哈希基础上变化
- 性能影响:冲突越多,生成短码越慢
Base62无冲突
为什么无冲突:因为每个ID都是唯一的
优势:
- 生成过程简单直接
- 性能稳定可预测
- 无需复杂的冲突处理逻辑
⚡ 性能对比
Hash方案的性能特点
生成短码时:
- 计算长网址的哈希值 (O(1))
- 查询数据库检查是否冲突 (数据库查询)
- 如果冲突,重新计算 (可能多次)
- 插入数据库 (数据库写入)
访问短码时:
- 直接根据短码查询数据库 (O(1))
Base62方案的性能特点
生成短码时:
- 获取下一个ID (可能是数据库自增,或分布式ID生成)
- Base62编码 (O(log n))
- 插入数据库 (数据库写入)
访问短码时:
- Base62解码得到ID (O(log n))
- 根据ID查询数据库 (O(1))
🎯 实际业务场景的考虑
用户体验差异
Hash方案:
- 用户重复提交相同URL → 得到相同短码
- 用户感知:"系统记住了我之前的请求"
- 适合:个人工具、内部系统
Base62方案:
- 用户重复提交相同URL → 每次得到不同短码
- 用户感知:"每次都是新的短码"
- 适合:商业服务、需要独立统计的场景
统计分析的差异
Hash方案统计困难:
Base62方案统计精确:
🔧 扩展性考虑
Hash方案的扩展问题
冲突率随数据增长:
- 数据量小时:冲突很少
- 数据量大时:冲突急剧增加
- 性能下降:需要多次重试才能找到可用短码
生日悖论效应:
即使哈希空间很大,当数据量达到√(哈希空间)时,冲突概率就很高了。
Base62方案的线性扩展
可预测的增长:
- 6位Base62:可表示62^6 ≈ 568亿个短码
- 7位Base62:可表示62^7 ≈ 3.5万亿个短码
- 性能稳定:无论数据量多大,生成速度都一样
💼 业务模式的影响
Hash方案适合的场景
个人/内部工具:
- 用户希望相同URL得到相同短码
- 不需要详细的访问统计
- 存储成本敏感
特点:
- 去重效果好
- 存储效率高
- 实现相对复杂
Base62方案适合的场景
商业服务:
- 需要为每个用户、每次请求独立统计
- 支持A/B测试、营销追踪
- 需要稳定可预测的性能
特点:
- 统计能力强
- 性能稳定
- 实现简单
🎯 选择建议
选择Hash方案的情况
- 存储成本敏感:相同URL只存一份
- 用户期望一致性:相同输入得到相同输出
- 访问量 >> 创建量:读多写少的场景
- 数据量可控:不会达到高冲突率的规模
选择Base62方案的情况
- 需要精确统计:每个短码独立跟踪
- 高并发写入:大量短码生成请求
- 商业化运营:需要用户隔离、营销追踪
- 长期扩展:预期数据量很大
💡 核心洞察
Hash方案的本质:把短码当作长网址的"别名"
- 优势:节省空间,去重效果好
- 劣势:冲突处理复杂,统计能力弱
Base62方案的本质:把短码当作"数据库主键的编码"
- 优势:性能稳定,统计能力强,实现简单
- 劣势:存储开销大,相同URL会重复存储
关键决策点:
- 如果你的业务更像"书签工具" → Hash方案
- 如果你的业务更像"营销平台" → Base62方案
现实中,大多数商业短网址服务(bit.ly、t.co等)都选择Base62方案,因为商业价值更多来自于数据分析和用户服务,而不是存储效率。
Bloom Filter应用
核心特性
Bloom Filter是一个概率性数据结构:
- 可能存在:如果BF说"存在",实际可能存在,也可能不存在(假阳性)
- 绝对不存在:如果BF说"不存在",那绝对不存在(无假阴性)
通俗理解:
就像一个"不太准确的门卫":
- 说"你不在名单里" → 100%准确,你确实不在
- 说"你在名单里" → 可能准确,也可能认错人了
🔍 在短网址系统中的应用场景
1. 短码存在性检查(最重要)
传统方式的问题:
使用Bloom Filter优化:
2. 缓存穿透防护
缓存穿透问题:
Bloom Filter防护:
3. 分布式去重检查
分布式环境的挑战:
Bloom Filter辅助方案:
🛠️ 具体实现方案
方案一:单层Bloom Filter
应用场景:基础的短码存在性检查
适用场景:
- 中小型短网址服务
- 对误判容忍度较高
- 内存资源充足
方案二:分层Bloom Filter
设计思路:用多个BF分别处理不同"热度"的数据
优势:
- 热点数据误判率极低
- 内存使用更高效
- 适合访问模式有明显热点的场景
方案三:Counting Bloom Filter
解决的问题:传统BF无法删除元素
📊 性能对比分析
数据库查询减少效果
无Bloom Filter:
有Bloom Filter(1%误判率):
缓存穿透防护效果
攻击场景测试:
⚖️ 权衡考虑
内存 vs 性能权衡
Bloom Filter大小对比:
一致性考虑
Bloom Filter更新滞后问题:
误判处理策略
业务层面的误判处理:
🎯 最佳实践建议
选择合适的BF方案
小型服务(<1000万短码):
- 单层Bloom Filter
- 误判率1%
- 内存占用<100MB
- 实现简单
中型服务(1000万-1亿短码):
- 分层Bloom Filter
- 热点数据0.1%误判率
- 历史数据1%误判率
- 平衡性能和内存
大型服务(>1亿短码):
- 分布式Bloom Filter
- 使用Redis Cluster存储
- 支持动态扩容
- 复杂但可扩展
监控和调优
关键监控指标:
💡 核心价值
Bloom Filter在短网址系统中的价值:
- 性能提升:减少90%+的无效数据库查询
- 成本降低:数据库压力减少,可以用更少的数据库资源
- 防攻击:有效防护缓存穿透攻击
- 用户体验:响应速度更快,特别是在高并发场景
适用的业务特点:
- 读多写少(短网址访问 >> 短网址创建)
- 大部分查询都是"不存在"的结果
- 对轻微误判有容忍度
- 追求高性能和低成本