为什么要用短链
- 长度限制
短信、微博等内容长度有限制,若其中连接缩短,则可编辑内容增加,利于节省费用、文案排版等 - 便于分享
长链二维码过于密集识别难度大,部分软件平台链接长度有限制,链接太长无法被识别
短链本质
链接标识与原链接的一对一映射
短链跳转的原理
- 浏览器请求短链
- 后端服务根据短链标识获取原链接
- 后端向浏览器返回301或302状态码与原链接
- 301 永久重定向 浏览器请求短链后会缓存原链接,再次请求时则会直接请求原链接,不利于数据统计
- 302 临时重定向 浏览器不会缓存原链接,每次请求都会先请求短链,便于统计链接访问数据
- 浏览器跳转到原链接
短链标识组成
短链标识一般由 0-9A-Za-z 62个数字与字母自负组成,若标识长度为6位,则完全容量多达568亿(62^6=56,800,235,584),能够满足绝大部分业务场景
短链生成
哈希算法(摘要算法)
- 选择标准
- 性能高
- 碰撞概率小
- 可选算法
- 非加密算法
- MurmurHash Google于2008年出品,随机分布特征表现良好,广泛应用于Redis、MemCacheH、Base
- 加密算法(不推荐)由于需要对数据进行加密,性能远低于非加密算法
- Md5 消息摘要算法
- SHA 安全散列算法
- 非加密算法
- 选择标准
随机字符串
- UUID(Universally Unique Identifier)
Id较长且无序,插入数据库是会导致频繁的页分裂,影响数据库性能,单一组件不能保证幂等性(页分裂)
- UUID(Universally Unique Identifier)
自增ID
一种无碰撞的方法,因为是有序数字,可能存在安全问题
- 数据库 自增主键,使用简单,实现方便,可以借助于唯一索引保证幂等性
- Redis 分布式全局唯一自增ID,需要手动实现,适用于分布式系统,单一组件不能保证幂等性
短链存储
基本数据:原链、短链标识、过期时间、访问次数(如果有需要)
数据库
持久存储,部分数据库拥有自增主键,可以同时实现短链标识的生成和存储工作,性能不及Hbase与Redis
缓存
- MemCache
本地缓存,无法持久化,适用于单机,建议与数据库搭配使用 - Redis
分布式缓存,存在数据过期机制,属于缓存类组件,数据无法持久化,不适用于大量数据存储, 性能较高
- MemCache
数据库+缓存
在业务量大,高并发的情况下,建议采用以下方案
- 数据库作为持久存储,存储所有的短链,保证业务容量
- Redis与MemCache作为两层缓存,弥补数据库性能的不足
Hash算法冲突解决
数据库
- 允许冲突存在,长链字段添加唯一索引,最终生成的短链标识可由Hash结果与数据库Id组合而成
- Hash结果作为最后的短链标识,数据库对Hash结果字段做唯一索引,若插入失败则需要在长链中拼接固定标识重新Hash
若存在多次冲突,则需要多次访问数据库,会导致性能下降
布隆过滤器
- 利用布隆过滤器可以有效地去重和解决冲突,但是会有误报
布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。
- 利用布隆过滤器可以有效地去重和解决冲突,但是会有误报
幂等性校验
可以通过对数据表原链接添加唯一索引进行幂等性校验,若短链生成QPS过高的情况下可以将热点数据
高并发解决方案
针对高并发的情狂可以使用openResty,它是一个基于 Nginx 与 Lua 的高性能 Web 平台,由于 Nginx 的非阻塞 IO 模型,使用 openResty 可以轻松支持 100 w + 的并发数,同时 openResty 也自带了缓存机制,集成了 redis 这些缓存模块,也可以直接连 mysql,不需要再通过业务层连这些中间件
示例代码
https://github.com/XiaoWeicheng/shorturl