十三、Redis进阶-实现访问频率限制

作者: 温新

分类: 【Redis】

阅读: 2665

时间: 2020-09-02 13:43:36

需求:限制每分钟每个用户最多只能访问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
请登录后再评论