Golang短链接访问统计核心是异步记录+原子计数:重定向前提取IP/Referer/UserAgent等字段,用goroutine异步保存VisitRecord,Redis INCR实现高性能计数,再批量落库;提供按短码查询总次数与最近访问明细的统计接口。
用 Golang 实现短链接访问统计,核心是:每次重定向前记录一次访问(次数 +1),同时提取并保存来源信息(如 Referer、User-Agent、IP、时间等)。关键在于不阻塞重定向响应,且保证数据可靠写入。
先定义访问记录结构,便于后续扩展:
type VisitRecord struct {
ID uint64 `json:"id"`
ShortCode string `json:"short_code"` // 对应的短码,如 "abc123"
IP string `json:"ip"`
Referer string `json:"referer"`
UserAgent string `json:"user_agent"`
Timestamp time.Time `json:"timestamp"`
}
存储建议:
INCR short:abc123:count)+ 异步落库(如写入 Kafka 或批量插入 MySQL/PostgreSQL)short_code、count、last_visited 字段,并为 short_code 建索引UPDATE ... SET count = count + 1
在重定向处理器中提取必要字段,异步记录(防止拖慢响应):
func redirectHandler(w http.ResponseWriter, r *http.Request) {
shortCode := strings.TrimPrefix(r.URL.Path, "/")
// 1. 查询原始 URL(假设从 DB/Cache 获取)
targetURL, err := getTargetURL(shortCode)
if err != nil {
http.Error(w, "Not found", http.StatusNotFound)
return
}
// 2. 提取访问信息(注意:Referer 可能为空或伪造)
ip := getClientIP(r)
referer := r.Referer()
userAgent := r.UserAgent()
// 3. 异步记录(推荐用 goroutine + channel 或 worker pool 控制并发)
go func() {
record := VisitRecord{
ShortCode: shortCode,
IP: ip,
Referer: referer,
UserAgent: userAgent,
Timestamp: time.Now(),
}
saveVisitRecord(record) // 实现可为 Redis INCR + 写入日志/DB
}()
// 4. 立即重定向(不影响用户感知)
http.Redirect(w, r, targetURL, http.StatusTemporaryRedirect)
}
说明:
getClientIP 应优先读 X-Forwarded-For(若部署在 Nginx/CDN 后),再 fallback 到 r.RemoteAddr
r 或 w,只传必要值(如上面已提取的字符串)提供 API 查看某短链的访问概况,例如 GET /api/stats/abc123:
func statsHandler(w http.ResponseWriter, r *http.Request) {
shortCode := chi.URLParam(r, "code")
// 获取总访问次数(Redis 或 DB)
totalCount, _ := getVisitCount(shortCode)
// 查询最近 10 条来源(可加 LIMIT/OFFSET)
recentVisits, _ := getRecentVisits(shortCode, 10)
json.NewEncoder(w).Encode(map[string]interface{}{
"short_code": shortCode,
"total_count": totalCount,
"recent_visits": recentVisits,
})
}
常见统计维度可扩展:
GROUP BY DATE(timestamp) 或 Redis Time Series)Referer 归类(识别来自微信、微博、邮件等)User-Agent 区分移动端/桌面端、浏览器类型PFADD short:abc123:ips )让统计更健壮、易用:
User-Agent 是否含 bot、spider、crawler,可跳过记录(视业务而定)INCR + EXPIRE 60)
:允许创建短链时携带 ?utm_source=xxx,重定向时保留,方便归因不复杂但容易忽略:记录要快,查询要准,存储要稳。从 Redis 计数起步,再逐步加入明细分析,就能支撑大多数短链运营场景。