我想知道如何使用Redis实现一个唯一的访客计数器,超时1小时。我有一个小的网上商店,我想显示有多少人正在看一篇文章目前。最好的方法是什么?我正在使用Predis
不慎多谢
最佳答案
你需要做两件事:
为每个访问者生成一个唯一的id(他们are many ways to do it)
使用redisSET
或ZSET
来存储这些id并添加过期机制。
方法1:设置+疤痕+过期
解决方案
集合名称可以是类似于[article_id]:[current_hour_timestamp]
的内容,每次您在其中输入访问者id时,都会执行SADD
操作。每一套都会在一段时间后过期。
使用EXPIRE
了解有多少访问者在线
笔记
如果您愿意的话,键可以是SCARD [article_id]:[current_hour_timestamp]
或任何类似的[article_id]:[current_hour_timestamp]
。
在每一个小时开始的集合将是空的,这不是你可能想要的。
方法2:zset+zcard+cron
解决方案
每次访问者阅读打开一篇文章发送一个articles:[article_id]:readers:[current_hour_timestamp]
,它是否重新加载页面并不重要,只会更新ZADD [article_id]:readers [expiry_time] [visitor_id]
。expiry_time
是将来当我们认为访问者离开了文章时的时间戳。
设置cron以每小时运行一次:
Retrieve all article ids in databases
For each article
Send a `zremrangebyscore "article.id:readers" -inf [current_timestamp]` to remove expired visitors_id
最后要检索当前读卡器计数,请运行
expiry_time
。注释
这种方法要好得多,因为它使用了滑动窗口,这样您就不会在每一个新的小时都有“0阅读器”的效果。但是缺点是,您需要循环遍历所有的文章id,这可能是一个问题。
方法3:zset+zcard+zset为索引+cron
解决方案
与方法2相同,但是此方法使用另一个zset
ZCARD [article_id]:readers
,其中包含最近更新的所有zset键。然后,您将不得不遍历这个zset成员,而不是所有的项目id。
注释
如果你这样下去,别忘了从
articles:readers:zset
中删除过期的成员!