缓存绕过不直接导致uv/pv失真,但会改变请求路径,使本应被缓存拦截的请求落到后端或统计脚本,造成重复计数、漏计或误标;需重点排查埋点位置、缓存覆盖范围、日志口径差异、redis hll一致性及双计/零计场景。

缓存绕过本身不直接导致UV/PV失真,但会改变请求路径和触发条件,让原本由缓存拦截的请求落到后端或统计脚本上,从而干扰原始统计逻辑。排查重点不是“有没有绕过”,而是“绕过后哪些访问被重复计入、漏计或误标”。
确认统计埋点是否落在缓存层之后
很多站点把PV/UV上报逻辑放在前端JS中(如页面加载时发Beacon),这类统计天然绕过CDN或反向代理缓存——只要页面HTML被缓存,JS就不会执行,PV就漏计;反之,若强制刷新或禁用缓存,JS执行了,但用户可能只是重试一次播放,却被记为两个UV。
- 检查统计脚本是否随HTML一起缓存:查看响应头中Cache-Control和ETag是否覆盖JS资源
- 对比CDN日志与应用服务器日志:若CDN命中率骤降,但PV激增,说明大量请求穿透到源站,而源站又执行了埋点,造成重复计数
- 视频类站点尤其注意:播放页HTML可缓存,但播放器初始化、play事件上报必须走真实用户行为,不能依赖缓存后端返回的静态HTML中的旧脚本
区分服务端统计与客户端统计的口径差异
绕过缓存后,部分请求会走到Nginx access_log或应用日志,此时若用日志解析方式统计PV/UV(例如按$uri或$remote_addr聚合),和前端JS上报的结果必然不一致——前者统计的是HTTP请求,后者统计的是页面级用户行为。
- 服务端日志统计PV:每条200/304响应都算一次,包括图片、字体、AJAX接口,需过滤只保留HTML类型请求(如匹配\.html?$或/video/\d+)
- 服务端日志统计UV:不能只靠$remote_addr,要结合User-Agent + IP + Cookie前缀做粗粒度去重,否则同一局域网用户全被合并
- 前后端统计结果偏差超过15%,应暂停归因,先对齐统计对象:是“页面打开”还是“播放开始”?是“首次加载”还是“任意刷新”?
检查Redis等中间件在UV统计中的状态一致性
不少站点用Redis的HyperLogLog(如pfadd)做UV去重,但缓存绕过可能导致多个实例或不同入口同时写入,而未做分布式锁或key分片,造成基数估算偏高。
- 查Redis中对应UV key的pfcount值,再用hgetall或scan确认是否有异常大key(比如单日写入千万级user_id)
- 比对绕过前后同一小时的UV增量:若绕过后每分钟pfadd调用量翻倍,但实际业务订单/播放完成数不变,大概率是埋点被多次触发(如播放页重定向两次、预加载脚本重复执行)
- 避免用IP直接进HLL:移动端IP频繁变化,应优先使用设备ID或登录态token哈希后写入
验证关键链路是否存在“双计”或“零计”场景
缓存策略变更后,最常见失真是同一用户行为被统计两次(如CDN未缓存JS,又在源站渲染时插入了第二套埋点),或完全没触发(如强缓存HTML,但新版本统计SDK未更新,旧脚本失效)。
- 抓取真实用户访问的完整Network记录,筛选出包含/log?event=pv或类似上报URL的请求,看是否出现重复路径、相同refer、相近时间戳
- 在测试环境模拟绕过:curl -H "Cache-Control: no-cache" 请求播放页,观察Nginx日志、浏览器控制台、Redis HLL三者UV值是否收敛
- 对播放类动作,务必分离“页面曝光”和“播放启动”两个事件:前者可缓存后统计,后者必须由播放器SDK在oncanplay后主动上报,不可依赖页面加载即发











