短码映射需避开三大坑:生成须用安全随机(如secrets.token_urlsafe(6))而非math.random()或md5;写入前必须exists校验防覆盖;跳转与计数须用lua脚本原子执行。

直接用 SET 存短码到长 URL 的映射就行,但必须避开三个坑:短码生成不可预测、写入前不校验导致覆盖、跳转+计数非原子操作。
短码生成不能靠 Math.random() 或简单哈希
用 Math.random() 生成 6 位字符串,线上并发一高就重复;用 MD5(long_url).substring(0,6) 看似省事,但 URL 尾部参数微调(比如 ?t=123 → ?t=124)就会产出完全不同短码,无法复用,还容易被枚举。
- 推荐方案:生成 6 字节随机字节数组,再用
base64url编码(不含+、/、=),得到约 8 个字符的短码,冲突概率低于 1e-9 - Python 示例:
secrets.token_urlsafe(6);Java 可用SecureRandom+ 自定义 base64url 编码 - 绝对不要用自增 ID 直接转 base62——暴露业务量、可遍历、无隐私性
SET 写入前必须 EXISTS short:abc123
Redis 的 SET 默认覆盖,如果两个请求几乎同时生成了相同短码,后写入的会把前一个映射覆盖掉,导致用户点短链跳错地址。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 正确流程:先
EXISTS short:xyz789,返回 0 再SET short:xyz789 "https://..." EX 3600 - 冲突时立刻重试(建议上限 3 次),别等业务层兜底
- Key 命名统一用
short:{code},Value 就存原始 URL 字符串,别 JSON 化——浪费内存、无必要
跳转 + 计数必须用 Lua 脚本原子执行
先 GET short:abc123,再 INCR stat:abc123,并发下可能漏计数。Redis 单命令是原子的,但多命令组合不是。
- 用 Lua 一次性完成:读 URL +
INCR访问量 + 返回 URL - 示例脚本:
local url = redis.call("GET", KEYS[1]); if url then redis.call("INCR", "stat:" .. ARGV[1]); end; return url - 调用:
EVAL ... 1 short:abc123 abc123,KEYS[1] 是映射 key,ARGV[1] 是短码用于构造统计 key - 注意:统计 key
stat:abc123和映射 keyshort:abc123分开存,避免单 key 过大或过期策略冲突
真正上线时,短码长度、过期时间、Lua 脚本是否预热、连接池配置这些细节,比算法本身更容易出问题——尤其是当短码被高频访问时,INCR 和 GET 的顺序颠倒或漏掉 EX 参数,故障会立刻暴露。










