搜索
当前位置:首页 > 知识 > 网页访问计数器

网页访问计数器

发表于 2026-10-17 05:58:41 来源:烟消火灭网

去年帮朋友搭了个小博客,网页他提了个需求:想知道每天有多少人来看。访问我第一反应是计数装个Google Analytics,他摆摆手说太重,网页就要个数字,访问页脚显示“您是计数第几位访客”那种。行,网页那就自己写一个。访问

网页访问计数器这东西,计数原理不复杂。网页核心就一句话:每次有人打开页面,访问让服务器把某个数字加一,计数再把这个数字返回给浏览器渲染出来。网页听起来像是访问十行代码能搞定的事,但真动手写,计数坑一个接一个。

最朴素的做法

假设你用PHP,最直觉的写法是这样:

<?php $file = 'counter.txt'; $count = (int)file_get_contents($file); $count++; file_put_contents($file, $count); echo "您是第 { $count} 位访客"; ?> 

这代码能跑,但有个致命问题——并发。两个人同时打开页面,A读到100,B也读到100,各自加一写回去,结果都是101。本该是102。访问量一上来,丢计数是必然的。文件锁能解决一部分问题,flock()加个排他锁,但性能立刻掉下来。每次请求都要排队等文件IO,页面加载速度肉眼可见地变慢。

我朋友那个博客一天也就几十个人看,用文件锁其实够了。但我想试试别的方案。

Redis的原子操作

换成Redis就舒服多了。Redis的INCR命令本身是原子性的,天然适合计数场景:

$redis = new Redis(); $redis->connect('127.0.0.1', 6379); $count = $redis->incr('page_views'); echo "您是第 { $count} 位访客"; 

没有锁,没有文件读写,单线程模型保证了原子性。速度快到可以忽略不计。但问题也来了——Redis重启,数据就没了。得配持久化,RDB或者AOF。我选了AOF,每秒同步一次,最多丢一秒的数据。对于一个博客计数器来说,丢一秒的访问量,完全可以接受。

不过这里还有个细节:INCR是全局计数,所有页面共用一个数字。如果你想知道每篇文章各自的访问量,得用HINCRBY,把文章ID作为field:

$redis->hIncrBy('article_views', $articleId, 1); 

这样每篇文章的计数独立,互不干扰。我朋友后来改口说想要每篇文章的阅读数,幸好一开始就用了Hash结构。

前端刷新的问题

计数器写好了,但每次刷新页面数字都加一。我自己调试的时候刷了二十几次,计数器直接飙到三十多。真实用户可能也会反复刷新,或者浏览器预加载、爬虫抓取,都会让数字虚高。

常见的做法是加一层去重。简单点的用Cookie,同一个浏览器一天内只计一次。但Cookie可以被清除,也可以被禁用。再复杂点用IP加User-Agent做指纹,存到Redis里设个过期时间。我选了后者,用SETNX加EXPIRE,同一个指纹24小时内只计一次。代码大概长这样:

$fingerprint = md5($ip . $userAgent); $key = "viewed:{ $fingerprint}"; if ($redis->setnx($key, 1)) {  $redis->expire($key, 86400); $redis->incr('page_views'); } 

这样刷新的问题基本解决了。但爬虫还是会漏进来一些,除非专门做User-Agent黑名单。我朋友说算了,爬虫那点量无所谓。

显示上的小把戏

数字直接显示出来有点单调。很多网站会把它做成图片,或者用等宽字体加个背景框,看起来像老式计数器。我朋友想要那种LED数字的效果,我找了段CSS,用text-shadow和monospace字体模拟了一下,效果还行。

还有个细节:数字太大不好看。十万以上的访问量,显示成“100,234”比“100234”舒服得多。PHP里用number_format()一行搞定。

最后上线那天,我朋友盯着页脚那个数字看了半天,说:“怎么才1?”我说你刷新一下。他刷新,变成2。他笑了,说这玩意还挺有意思。

其实网页访问计数器就是这么个东西——技术含量不高,但真要做得好用,得考虑并发、持久化、去重、显示效果。每一个环节都有取舍。选什么方案,取决于你对“准确”和“性能”的容忍度。像我朋友那种小博客,Redis加个去重就够了。换成日PV百万的站点,可能得上Kafka加Flink做实时流处理。工具没有好坏,只有合不合适。

随机为您推荐
友情链接
版权声明:本站资源均来自互联网,如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

Copyright © 2016 Powered by 网页访问计数器,烟消火灭网   sitemap

回顶部