·更新于 2026年10月25日· 1 次浏览 Nuxt 3Vue 3Node.jsRedisMongoDB工程实践SEO流量统计

Nuxt 3 阅读量被刷新刷高:我用 Redis HyperLogLog、有效停留和来源过滤做真实统计

一次后台阅读量异常暴涨,让我意识到简单 +1 统计会被刷新、爬虫和广告参数污染。于是把阅读链路改成可去重、可过滤、可回查的方案。

Nuxt 3 阅读量被刷新刷高:我用 Redis HyperLogLog、有效停留和来源过滤做真实统计 封面
ZHOUYI

作者

ZHOUYI

晚上看后台,一篇文章阅读量突然多出几千次。刚开始以为是推荐流量,点开日志发现大量同 IP 高频访问,还有自己反复预览、广告参数落地、爬虫抓取。原来的逻辑是详情页请求成功就 +1,刷新一次涨一次,数字好看但完全不能代表真实阅读。

先把“打开页面”改成“有效停留”

我没有在 Nuxt 3 页面初始化时直接上报,而是记录进入时间,等用户离开或页面隐藏时再判断。一般要求停留超过一个阈值,并且没有刚进来就切走。前端只负责采集,是否计数放到服务端判断,避免浏览器端被随意绕过。

用 Redis HyperLogLog 做低成本去重

HyperLogLog 的好处是省内存,适合这种允许少量误差的计数场景。我把指纹做成短期哈希,结合文章 ID 和日期,避免把普通访客当成同一人长期追踪。阅读量不是计费,不需要绝对精确,但要能挡住明显重复。

js
const key = `read:hll:${articleId}:${day}`;
const added = await redis.pfadd(key, fingerprint);
if (!added) return { counted: false };
const stayedMs = Date.now() - Number(enterAt || 0);
if (stayedMs < 8000 || hiddenTooSoon) return { counted: false };
await redis.incr(`read:valid:${articleId}:${day}`);
await ReadEvent.create({ articleId, fingerprint, stayedMs, ua, referrer });
return { counted: true };

来源指纹和规则过滤

  1. 同一文章当天同指纹只算一次,HyperLogLog 判断新增。
  2. 停留过短、无可见性变化、频繁刷新的请求不计入。
  3. 广告参数、异常 UA、高频 IP 先进入灰名单,只记录不计数。
  4. 正文页参与统计,参数聚合页和预览页不参与,避免 SEO 参数稀释。

计数通过后,Redis 先做原子自增,保证实时数字稳定;MongoDB 再异步写入阅读事件,方便后续回查和修正。发现误判时,我不会直接改总数,而是重跑当天聚合,让数字有来源、有证据。

“阅读量不是虚荣指标。与其追求数字上涨,不如早点把无效流量挡在外面。简单 +1 很容易,但能解释每一次增长,才算真正做完。”

Guestbook

留言

若这篇文章也曾停在你心上,留一行字吧,我会看的。

先确认一下邮箱

多这一步,是为了少些机器骚扰,也让我能更踏实地读每一条真人写下的字。验证码 10 分钟内有效;同一邮箱 60 秒内只能发一封。

本文留言

共 0 条已加载 0 条

这里还静悄悄的——愿意做第一个留下脚印的人吗?