十三、Redis进阶-实现访问频率限制
需求:限制每分钟每个用户最多只能访问100个页面
解决思路
1)为用户取一个有意义的String键名,用户每次访问使用incr命令递增该键的值
2)递增后值为1(第一次访问),则为该键设置过期时间60秒
3)该键值超过100,则进行限制
实现方式一 Sting
伪代码实现
# 判断该键是否存在,存在返回1,不存在返回0
$isKeyExists = exists rate.limiting:$userId
if $isKeyExists is 1
$times = incr rate.limiting:$userId
# 判断用户访问是否超过限制
if times > 100
echo 频繁访问,请稍后再试
exit
else
multi
incr rate.limiting:$userId
expire $keyName 60
exec
实现方式二 List
方式一存在的问题,如果一个用户在第一分钟的最后一秒访问了99次,在下一分钟的第一秒访问了100次,相当于在两秒访问了199次, 与一分钟内最多只能访问100次相比还是差距比较大,尽管这种情况比较极端,但是依然存在。如果要实现粒度更小的控制方式,精确的保证每分钟最多访问100次,就需要使用第二种方案。
如果键中的元素超过100个,就判断时间最早的元素距离现在的时间是否小于1分钟,如果是,则表示用户最近1分钟的访问次数超过100次,如果不是就将当前时间加入列表中,同时把最早的元素删除。
伪代码实现
# 获取列表长度
$limitLength = llen rate.limting:$userId
# 判断是否超过限制
if $limitLength < 100
lpush rate.limiting:$userId now()
else
# 获取最后一个元素
$time = lindex rate.limiting:$userId -1
if now() - $time < 60
echo 频繁访问,请稍后再试
else
lpush rate.limiting:$userId now()
# 删除0~99以外的元素
ltrim rate.limiting:$userId 0 99
请登录后再评论