短链接用62进制而非16进制,因62进制(0–9+a–z+a–z)字符更多,6位可编码约568亿id,远超16进制的1677万,抗暴力猜测更强,且天然url友好、无特殊符号。

短链接为什么用 62 进制而不是 16 进制
因为 16 进制(0–9 + a–f)只有 16 个字符,生成的 ID 映射太短,容易被暴力猜出原始 URL;而 62 进制(0–9 + a–z + A–Z)提供 62 个唯一字符,同样长度下能编码更大范围的整数——比如 6 位 62 进制数可表示约 568 亿个 ID,够中小项目长期使用。
关键不是“进制多高级”,而是要避开易混淆字符(如 0 和 O、1 和 l),实际常用的是精简版 62 进制表,例如:'23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'(去掉了 0O1lI 等)。
PHP 中怎么把自增 ID 转成短码(encode)
核心是模拟“除 k 取余”过程,但不能直接用 base_convert(),它不支持自定义字符集,也不处理 0 的边界情况。
实操建议:
- 用循环对 ID 做取模和整除,每次取
$chars[floor($id % 62)],然后$id = floor($id / 62) - ID 为 0 时需单独返回第一个字符(否则循环不执行),即
if ($id === 0) return $chars[0]; - 结果字符串要
strrev(),因为余数是从低位开始取的 - 不要用递归实现,大 ID(如 >1e6)可能触发 PHP 栈溢出
示例片段:
$chars = '23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ';
function idToShort($id, $chars) {
if ($id === 0) return $chars[0];
$short = '';
while ($id > 0) {
$short .= $chars[$id % 62];
$id = (int)($id / 62);
}
return strrev($short);
}
怎么把短码还原回 ID(decode)
这是 encode 的逆过程:从左到右遍历字符,在 $chars 中查索引,按位权累加。注意大小写敏感,strpos() 比 array_search() 更快且不依赖键名。
常见错误现象:
- 输入含非法字符(如
-、_、空格)导致strpos()返回false,后续计算崩掉 → 应提前用preg_match('/^[2-9a-zA-Z]+$/', $short)校验 - 没处理空字符串或超长串(如 >10 位),可能隐式转换出错 → 建议限制长度为 2–8 位
- 用
pow(62, $i)计算位权,浮点误差在高位时会导致 ID 偏移 → 改用整型累乘:$multiplier *= 62
示例片段:
function shortToId($short, $chars) {
if (!preg_match('/^[2-9a-zA-Z]{2,8}$/', $short)) return false;
$id = 0;
$multiplier = 1;
for ($i = strlen($short) - 1; $i >= 0; $i--) {
$pos = strpos($chars, $short[$i]);
if ($pos === false) return false;
$id += $pos * $multiplier;
$multiplier *= 62;
}
return $id;
}
数据库怎么存、怎么防重复和并发冲突
短码本质是 ID 的“别名”,不是随机字符串,所以不能靠 uniqid() 或 random_bytes() 生成——那样无法反解,也丧失映射确定性。
必须基于主键 ID 编码,因此流程是:插入原始 URL → 获取自增 ID → encode 成短码 → 更新该记录的 short_code 字段。
容易踩的坑:
- 不加事务,高并发下可能两个请求拿到相同 ID 并生成相同短码 → 必须用
INSERT ... ON DUPLICATE KEY UPDATE或先SELECT FOR UPDATE - 短码字段没建唯一索引,重复插入失败后没兜底重试 →
short_code列必须加UNIQUE索引 - 用 MyISAM 引擎,不支持行锁 → 换 InnoDB,配合事务和
INSERT ... SELECT避免竞态
真正难的不是算法,是确保「ID → 短码」全程幂等,且数据库层面不允许多个 URL 映射到同一短码。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











