Scan QR Code Upload QR Code
Domain Store
Select platform types to avoid link blocking
Select allowed platform types

生成短链接

短链接这东西,大家早就用习惯了。电商短信里那一小串字符,微博正文里被压缩过的网址,背后其实是同一套逻辑:把 https://www.example.com/very/long/url/with/parameters 这种又长又难看的地址,变成 https://short.ly/abc123 这样方便传播的样子。原理一句话就能说清——给每条长链接生成一个唯一标识符,存好两者之间的映射关系,有人访问时查一下库、跳过去就行。不过概念虽然简单,真要把每个环节做扎实,值得聊的细节可不少。

整个生成流程可以拆成四步。第一步是接收用户提交的原始长链接,可能是商品页、活动页,也可能后面拖着一串参数。接下来是最核心的环节:生成唯一标识符,也就是常说的 Key,这里常见三条技术路线。最直观的是哈希算法:拿 MD5 或 SHA-256 对长链接做摘要,得到固定长度的哈希值后截取一段当 Key,比如 https://www.example.com/product/12345 经过处理得到 d41d8cd98f00b204e9800998ecf8427e,取前六位 d41d8c 就能用。第二条路线是自增 ID:靠数据库给每条新链接分配一个递增的数字,再把这个数字转成 62 进制(用 a-z、A-Z、0-9 拼出来),位数一下子就压了下来。还有一种更省事的办法——直接生成固定长度的随机字符串,比如六位,然后到库里查一遍确认没人用过,撞车了就重新摇一个。



Key 有了,第三步是落库。映射表里一般要存这么几个字段:Key 本身、对应的长链接、累计访问次数、创建时间;需要控制有效期的话,再加一个过期时间。最后一步最简单,把 Key 拼到短域名后面,https://short.ly/d41d8c 就可以交付给用户了。

那用户点开短链接时会发生什么?请求到达服务器后,系统从 URL 里取出 Key,拿着它去数据库查出原始长链接,然后返回一个 301 或 302 重定向响应,浏览器收到后自动跳转过去。对普通用户来说,整个过程就是页面一闪而过,几乎无感。



流程听起来顺理成章,可真正动手实现时,有几个坎是绕不开的。

最要紧的是 Key 的唯一性。哈希可能碰撞,随机串可能撞车,所以生成之后必须查库确认,一旦冲突就得换。想从根上缓解这个问题,可以引入分布式 ID 生成器,Twitter 的 Snowflake 算法就是经典选择;或者给哈希加点随机盐值,进一步压低碰撞概率。

域名的选择也有讲究。bit.ly、t.cn 这类超短域名天然适合压缩长度;企业如果想强化品牌感,完全可以申请专属短域名,像 go.example.com 这样,既短又自带辨识度。

并发量一大,架构就得跟上。Key 查询是最高频的操作,用 Redis 之类的缓存顶在前面,大部分查询压力就落不到数据库头上;入口层再通过 Nginx 做负载均衡,把请求分摊开,避免单点故障。安全方面同样不能松懈:对同一 IP 的生成频率做限制,防止接口被刷;涉及用户 ID 之类的敏感信息,先做哈希处理再存储。

下面这段 Python 代码是一个最小可用的实现,把上面说的流程完整串了一遍:

import hashlib
import base64
import sqlite3

<img src="/uploads/20251015/10.png?t=1913857984" alt="" class="img-fluid" />

<h1>数据库初始化</h1>
conn = sqlite3.connect('short_links.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS links (
id INTEGER PRIMARY KEY AUTOINCREMENT,
long_url TEXT NOT NULL,
short_key TEXT NOT NULL UNIQUE,
clicks INTEGER DEFAULT 0)''')
conn.commit()

def generate_short_key(long_url):
# 使用MD5哈希生成唯一Key
hash_object = hashlib.md5(long_url.encode())
raw_key = hash_object.hexdigest()[:8] # 取前8位
# 转换为62进制
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
base62_key = ''
num = int(raw_key, 16) # 转换为10进制
while num > 0:
num, rem = divmod(num, 62)
base62_key = chars[rem] + base62_key
return base62_key.zfill(6) # 补齐到6位

def create_short_link(long_url):
short_key = generate_short_key(long_url)
# 检查是否已存在
c.execute('SELECT * FROM links WHERE short_key=?', (short_key,))
if c.fetchone():
raise ValueError("Key冲突,请重试")
# 插入数据库
c.execute('INSERT INTO links (long_url, short_key) VALUES (?, ?)', (long_url, short_key))
conn.commit()
return f"https://short.ly/{short_key}"

<h1>示例</h1>
long_url = "https://www.example.com/product/12345"
short_link = create_short_link(long_url)
print(short_link)


代码逻辑很直白:哈希取段、转 62 进制、查重、入库,最后拼出短链接。当然,这只是教学级的演示,真要上生产环境,还得补上并发控制、缓存层和更严谨的冲突重试机制。



短链接为什么无处不在?看看应用场景就明白了。社交媒体上,微博、抖音对字数和排版都有限制,长链接很容易被截断,短链接传播起来干净利落;做营销活动时,运营可以借助短链接后台的点击统计,追踪各个渠道的投放效果;二维码里嵌的其实也是链接,内容越短,码的密度就越低、越好扫;邮件营销里用短链接换掉长串地址,正文清爽了,阅读体验也跟着上去。

说到底,短链接的技术内核就是"唯一标识符、映射存储、重定向"这三件套。难点从来不在概念本身,而在工程细节的权衡——Key 怎么生成才能兼顾长度与唯一性,域名怎么选,存储和缓存怎么搭配才扛得住流量。把这些问题都想清楚了,一个稳定可靠的短链接服务才算真正立起来。