短链接服务应避免过度设计:用自增id转62进制生成唯一短码,配合insert on conflict兜底;重定向按需选302(可变)或301(永久);初期无需redis,数据库索引优化后足以支撑高qps。

短链接服务不需要用 Go 写得“高大上”,核心是:避免重复、控制跳转、能扛量。Go 本身适合,但很多人一上来就套 Web 框架 + ORM + Redis,反而把简单事搞崩。
怎么生成唯一短码而不撞车
别用 rand.String(6) 直接生成再查库——并发一高,重复插入失败或覆盖风险陡增。更稳的方式是“先算后存”,用自增 ID 做基础,再做进制转换:
- 用数据库(如 PostgreSQL)的
serial或 MySQL 的AUTO_INCREMENT获取唯一整数 ID - 把 ID 转成 62 进制(0-9a-zA-Z),例如
12345 → "3d7",长度可控且无碰撞 - 写入时用
INSERT ... ON CONFLICT DO NOTHING(PostgreSQL)或INSERT IGNORE(MySQL)兜底
这样既不用锁表,也不依赖随机性,ID 自增还天然有序,方便后续按时间范围归档。
HTTP 重定向必须用 301 还是 302
取决于你是否允许客户端缓存跳转结果:
- 业务初期、短链可能频繁修改目标 URL?用
http.Redirect(w, r, target, http.StatusFound)(即 302) - 短链一旦生成就永久固定,且希望 CDN/浏览器缓存跳转?用
http.Redirect(w, r, target, http.StatusMovedPermanently)(301) - 注意:301 一旦发出,Chrome 等浏览器会强缓存,改目标地址后用户可能刷不出来
多数内部或运营类短链服务建议默认 302,等数据稳定、访问量上来后再按需切 301。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
为什么别急着加 Redis 缓存
短链跳转本质是“单次读 + 即时响应”,QPS 高但逻辑极轻。直接查数据库在合理优化下完全够用:
- 给
short_code字段加唯一索引,PostgreSQL 查一条通常 - MySQL 开启
query_cache_size = 0(8.0+ 已移除)反而更稳,避免缓存失效抖动 - 真到单机扛不住时,优先水平拆分(按短码哈希分库),而不是加一层 Redis 引入序列化和网络延迟
过早引入 Redis,反而让部署变重、故障面扩大——比如 Redis 挂了,所有短链全 500。
如何防止恶意刷短链和跳转污染
上线第一天就可能被爬虫扫或被填进钓鱼页面。必须前置过滤:
- 创建接口校验
target_url:拒绝javascript:、data:、内网地址(如192.168.x.x)、未备案域名(可对接工信部公开 API) - 限制单 IP 每分钟创建不超过 5 条,用内存计数器(
sync.Map+ 定时清理)即可,别一上来就上 Redis RateLimiter - 跳转前加一层中间件检查
short_code是否在黑名单(比如被举报的),用map[string]struct{}加读锁,比查库快一个数量级
安全不是加个 WAF 就完事,而是从 URL 解析、存储、跳转三处各卡一道,每道都轻量但有效。
短链接真正的复杂点不在“怎么跳”,而在“谁在用、怎么管、坏了怎么查”。比如日志要带原始 User-Agent 和 Referer,数据库字段要预留 created_by 和 expires_at,这些比选什么框架重要得多。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










