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"` }
存储建议:
- 高频写入场景(如每秒数百次访问)→ 优先用 Redis 计数(
INCR short:abc123:count)+ 异步落库(如写入 kafka 或批量插入 mysql/postgresql) - 中小流量或开发验证 → 直接用 sqlite 或 PostgreSQL,建表含
short_code、count、last_visited字段,并为short_code建索引 - 避免每次访问都同步查库更新计数,可用原子操作或数据库
UPdate ... SET count = count + 1
二、http 处理器中安全记录访问
在重定向处理器中提取必要字段,异步记录(防止拖慢响应):
立即学习“go语言免费学习笔记(深入)”;
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 - goroutine 中不要直接使用
r或w,只传必要值(如上面已提取的字符串) - 高并发下建议用带缓冲的 channel 或轻量 worker 池,避免 goroutine 泛滥
三、统计接口:按需聚合查询
提供 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, }) }
常见统计维度可扩展:
- 按小时/天的访问趋势(需存带时间戳的明细,用 SQL
GROUP BY DATE(timestamp)或 Redis Time Series) - 按
Referer归类(识别来自微信、微博、邮件等) - 按
User-Agent区分移动端/桌面端、浏览器类型 - 独立 IP 数(需去重,适合用 Redis
PFADD short:abc123:ips <ip></ip>)
四、实用增强建议
让统计更健壮、易用:
- 忽略爬虫:检查
User-Agent是否含bot、spider、crawler,可跳过记录(视业务而定) - 防刷机制:对同一 IP 短时间内多次访问同一短链,可限频(如 Redis
INCR + EXPIRE 60) - 支持 UTM 参数透传:允许创建短链时携带
?utm_source=xxx,重定向时保留,方便归因 - 导出能力:提供 csv 下载接口,基于时间范围和筛选条件导出明细
- 前端埋点备用:除服务端重定向统计外,也可在落地页注入 JS 统计脚本,补全客户端行为(如页面停留时长)
不复杂但容易忽略:记录要快,查询要准,存储要稳。从 Redis 计数起步,再逐步加入明细分析,就能支撑大多数短链运营场景。