发布于2026-07-10 阅读(0)
扫一扫,手机访问
很多人在实现短链接时都会遇到一个选择——到底用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等)。
核心思路是模拟“除k取余”的过程,但不能直接用base_convert()——它不支持自定义字符集,也不处理0的边界情况。
实践中的做法是:
$chars[floor($id % 62)],然后$id = floor($id / 62)。if ($id === 0) return $chars[0];。strrev(),因为余数是从低位开始取的。示例代码:
$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);}这是encode的逆过程:从左到右遍历字符,在$chars中查索引,按位权累加。注意大小写敏感,strpos()比array_search()更快,且不依赖键名。
容易踩的坑:
-、_、空格)会导致strpos()返回false,后续计算直接崩掉——提前用preg_match('/^[2-9a-zA-Z]+$/', $short)校验一下就好。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字段。
这里有几个常见的坑:
INSERT ... ON DUPLICATE KEY UPDATE或先SELECT FOR UPDATE。short_code列必须加UNIQUE索引。INSERT ... SELECT来避免竞态。真正考验功夫的往往不是算法本身,而是确保“ID → 短码”整个过程幂等,并且在数据库层面不允许出现多个URL映射到同一个短码的情况。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8