在实际开发过程中,经常会遇到一些有实效性的数据,比如限时优惠、缓存、验证码等等,过了一段时间后就应该删除这些数据。如果用关系型数据库,那么就需要在表中增加一个字段存储实效时间,然后定时轮询该字段并判断删除。而在redis中,可以使用expire
命令给key设置有效时间来实现这个需求。
expire key seconds #设置key的有效时间 单位为秒
ttl key #获取key的剩余有效时间
persist key #设置有时效性的key为持久key
注意,对有实效性的key使用set会字段取消实效设置,变成持久key。
示例:
127.0.0.1:6379> set session:a34d zhangsan
OK
127.0.0.1:6379> expire session:a34d 20
(integer) 1
127.0.0.1:6379> ttl session:a34d
(integer) 2
127.0.0.1:6379> ttl session:a34d
(integer) -2
127.0.0.1:6379> get session:a34d
(nil)
127.0.0.1:6379> set session:a34d 40
OK
127.0.0.1:6379> ttl session:a34d
(integer) -1
127.0.0.1:6379> expire session:a34d 30
(integer) 1
127.0.0.1:6379> ttl session:a34d
(integer) 22
127.0.0.1:6379> persist session:a34d
(integer) 1
127.0.0.1:6379> ttl session:a34d
(integer) -1
127.0.0.1:6379> get session:a34d
"40"
127.0.0.1:6379>
1)限制具体IP在某个时段内的访问次数
有时,出于对网站的保护,我们需要对同一个ip的访问频率做出限制,以防止黑客攻击、网络爬虫给网站造成负载过大甚至崩溃。
对于这个需求,利用具有时效性的key就可以很好的解决。例如,限制每个用户每分钟最多访问网站100次,对应的思路就是:
对每一个用户创建一个名为rate.limiting:userip的键
设置改键的生存时间为1分钟
每次用户访问时,首先读取这个键的键值
判断是否超过100
使用incr命令将该键值+1
有效时间到,键自动删除
用户再访问时,重建该键,循环往复
伪代码如下:
$isKeyExists = exists rate.limiting:$ip
#如果存在
if $isKeyExists is 1
$times = incr rate.limiting:$ip
if $times > 100
print "post limit"
exit
else
incr rate.limiting:$ip #自动创建并初始值1
expire rate.limiting:$ip 60
上面的代码有一个非常严重的潜在问题,如果成行在运行完inr rate.limiting:$ip
后因为某种原因退出了,那么这个key就没有被设置有效时间,此后,这个ip在访问网站时,就会跳过访问频率的限制。
我们可以利用reids提供的事务能力对上面的代码进行改写:
$isKeyExists = exists rate.limiting:$ip
#如果存在
if $isKeyExists is 1
$times = incr rate.limiting:$ip
if $times > 100
print "post limit"
exit
else
mulit
incr rate.limiting:$ip #自动创建并初始值1
expire rate.limiting:$ip 60
exec