08-实现访问频率限制之一
4.2.2 实现访问频率限制之一
回到小白的问题,为了减轻服务器的压力,需要限制每个用户(以IP计)一段时间的最大访问量。与时间有关的操作很容易想到 EXPIRE 命令。
例如要限制每分钟每个用户最多只能访问100个页面,思路是对每个用户使用一个名为 rate.limiting:用户 IP 的字符串类型键,每次用户访问则使用 INCR 命令递增该键的键值,如果递增后的值是1(第一次访问页面),则同时还要设置该键的过期时间为1分钟。这样每次用户访问页面时都读取该键的键值,如果超过了100就表明该用户的访问频率超过了限制,需要提示用户稍后访问。该键每分钟会自动被删除,所以下一分钟用户的访问次数又会重新计算,也就达到了限制访问频率的目的。
上述流程的伪代码如下:
$isKeyExists = EXISTS rate.limiting:$IP
if $isKeyExists is 1
$times = INCR rate.limiting:$IP
if $times > 100
print 访问频率超过了限制,请稍后再试。
exit
else
INCR rate.limiting:$IP
EXPIRE $keyName, 60
这段代码存在一个不太明显的问题:假如程序执行完倒数第二行后突然因为某种原因退出了,没能够为该键设置过期时间,那么该键会永久存在,导致使用对应的IP的用户在管理员手动删除该键前最多只能访问100次博客,这是一个很严重的问题。
为了保证建立键和为键设置过期时间一起执行,可以使用上节学习的事务功能,修改后的代码如下:
$isKeyExists = EXISTS rate.limiting:$IP
if $isKeyExists is 1
$times = INCR rate.limiting:$IP
if $times > 100
print 访问频率超过了限制,请稍后再试。
exit
else
MULTI INCR rate.limiting:$IP
EXPIRE $keyName, 60
EXEC