当前位置:首页 > 问答 > 正文

用Redis怎么快速搞定网站访客数统计,简单又高效的办法分享

想起之前看过一篇来自“程序员小灰”的博客,里面讲过一个用Redis做实时数据统计的思路,特别适合咱们这种想快速上手的,今天要说的网站访客数统计,就是一个最典型的应用场景,咱们不扯那些复杂的概念,就用最简单、最直接的方式,看看怎么用Redis这个“超级快的字典”把事儿给办了。

核心思想:用钥匙直接开锁

你可以把Redis想象成一个挂在内存里的大钥匙柜,每个钥匙都有自己的编号,对应一个值,我们要统计网站访客数,最朴素的想法就是:每来一个访客,我就去把这个总数加1,在Redis里,有一个指令天生就是干这个的,叫做INCR。(来源:Redis官方命令文档)

这个INCR命令特别简单,你给它一个钥匙的名字,比如叫website:visits:total,它就会检查这个钥匙对应的值是不是数字,如果是,就给它加1;如果不是数字或者根本不存在,它就先把值当成0,然后加1,变成1,整个过程是一个原子操作,意思就是哪怕同一时刻有成千上万个访客同时点击网站,Redis也会排着队一个一个地加,绝对不会出现少算或者多算的情况,这就是内存数据库的速度和可靠性。

最最简单的办法,就是在你的网站代码里,无论是前端页面埋点还是后端接口处理,每当有一个新的独立页面被访问时,就执行这么一行命令:

INCR website:visits:total

这样,你想看总访客数的时候,只需要再用一个GET website:visits:total命令,瞬间就能拿到当前累计的总数,简单到令人发指,而且速度飞快,因为全是内存操作。

进阶一点:按天统计,看看趋势

光有一个总数往往是不够的,老板或者产品经理肯定会问:“那今天来了多少人?昨天呢?上周这个时候呢?” 这时候,我们就需要按天来统计了,办法还是一样简单,只不过我们把钥匙的名字带上日期就行了。(来源:基于Redis官方命令的常见实践)

用Redis怎么快速搞定网站访客数统计,简单又高效的办法分享

今天是2023年10月27日,我们就创建一个钥匙叫website:visits:20231027,每来一个访客,我们就执行:

INCR website:visits:20231027

同理,明天就是website:visits:20231028,这样,每天的数据都独立存储在一个键里,查询某一天的访客数,直接GET那一天的键名即可,想计算一周的总量?那就把这一周7天的键都取出来,把值加起来就行了,虽然需要一点简单的后期计算,但数据获取本身依然非常快。

再灵活一点:区分不同页面的访问量

有时候我们还想知道首页、产品页、新闻页各自被访问了多少次,思路完全一样,就是把钥匙的名字设计得更具体。(来源:常见Web分析场景的通用做法)

用Redis怎么快速搞定网站访客数统计,简单又高效的办法分享

  • 首页访问量:INCR page:visits:/index
  • 产品页访问量:INCR page:visits:/product/123
  • 新闻页访问its:/news/456`

这样,你就能轻松统计出各个页面的热度了。

独立访客”的提醒

这里要特别注意一下,上面这种方法统计的是“页面浏览量”(Page View),或者说“访问次数”,它并不能区分同一个用户是否多次访问,比如一个用户一天内刷新了10次首页,那就会算作10次访问。

如果你想统计的是“独立访客数”(Unique Visitor),也就是基于用户身份去重后的数量,那就需要用到Redis的集合(Set)或者HyperLogLog数据结构了,集合能存储不重复的元素,你可以把每个访客的唯一标识(比如经过哈希处理的IP地址或用户ID)塞进一个集合里,然后通过查询集合的大小来得到独立访客数,HyperLogLog则是一种更节省空间的黑科技,它用极小的内存就能估算出巨大集合的基数(不重复元素个数),虽然有一点点误差,但对于亿级流量的统计来说是完全可接受的,因为它太省内存了。(来源:Redis官方文档关于HyperLogLog的介绍)

对于大多数中小型网站来说,一开始用INCR来统计总访问次数和按天、按页面的访问量,已经完全够用且非常高效了,它的优势就在于:

  1. 极其简单:几乎零学习成本,一个命令搞定写入,一个命令搞定读取。
  2. 性能无敌:Redis单机每秒能处理十万甚至百万级别的INCR操作,应对普通网站流量绰绰有余。
  3. 理解直观:数据模型简单明了,不容易出错。

等你以后网站规模真的做大了,遇到了性能瓶颈或者有更精细的统计需求,再考虑引入集合、HyperLogLog或者更专业的统计系统也不迟,起步阶段,就用INCR这个“傻瓜式”操作,快速把功能实现上线,把精力集中在业务本身,这才是最聪明和省力的做法。