当前位置:嗨网首页>书籍在线阅读

09-实现访问频率限制之二

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

4.2.3 实现访问频率限制之二

事实上,4.2.2节中的代码仍然有个问题:如果一个用户在一分钟的第一秒访问了一次博客,在同一分钟的最后一秒访问了9次,又在下一分钟的第一秒访问了10次,这样的访问是可以通过现在的访问频率限制的,但实际上该用户在2秒内访问了19次博客,这与每个用户每分钟只能访问10次的限制差距较大。尽管这种情况比较极端,但是在一些场合中还是需要粒度更小的控制方案。如果要精确地保证每分钟最多访问10次,需要记录下用户每次访问的时间。因此对每个用户,我们使用一个列表类型的键来记录他最近10次访问博客的时间。一旦键中的元素超过 10 个,就判断时间最早的元素距现在的时间是否小于1分钟。如果是则表示用户最近1分钟的访问次数超过了10次;如果不是就将现在的时间加入到列表中,同时把最早的元素删除。

上述流程的伪代码如下:

$listLength = LLEN rate.limiting:$IP
if $listLength < 10
  LPUSH rate.limiting:$IP, now()
else
  $time = LINDEX rate.limiting:$IP, -1
  if now() - $time < 60
     print 访问频率超过了限制,请稍后再试。
  else
    LPUSH rate.limiting:$IP, now()
    LTRIM rate.limiting:$IP, 0, 9

代码中 now() 的功能是获得当前的Unix时间。由于需要记录每次访问的时间,所以当要限制“A时间最多访问B次”时,如果“B”的数值较大,此方法会占用较多的存储空间,实际使用时还需要开发者自己去权衡。除此之外该方法也会出现竞态条件,同样可以通过脚本功能避免,具体在第6章会介绍到。